@kodrunhq/opencode-autopilot 0.1.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/LICENSE +21 -0
- package/README.md +1 -0
- package/assets/agents/placeholder-agent.md +13 -0
- package/assets/commands/configure.md +17 -0
- package/assets/commands/new-agent.md +16 -0
- package/assets/commands/new-command.md +15 -0
- package/assets/commands/new-skill.md +15 -0
- package/assets/commands/review-pr.md +49 -0
- package/assets/skills/.gitkeep +0 -0
- package/assets/skills/coding-standards/SKILL.md +327 -0
- package/package.json +52 -0
- package/src/agents/autopilot.ts +42 -0
- package/src/agents/documenter.ts +44 -0
- package/src/agents/index.ts +49 -0
- package/src/agents/metaprompter.ts +50 -0
- package/src/agents/pipeline/index.ts +25 -0
- package/src/agents/pipeline/oc-architect.ts +49 -0
- package/src/agents/pipeline/oc-challenger.ts +44 -0
- package/src/agents/pipeline/oc-critic.ts +42 -0
- package/src/agents/pipeline/oc-explorer.ts +46 -0
- package/src/agents/pipeline/oc-implementer.ts +56 -0
- package/src/agents/pipeline/oc-planner.ts +45 -0
- package/src/agents/pipeline/oc-researcher.ts +46 -0
- package/src/agents/pipeline/oc-retrospector.ts +42 -0
- package/src/agents/pipeline/oc-reviewer.ts +44 -0
- package/src/agents/pipeline/oc-shipper.ts +42 -0
- package/src/agents/pr-reviewer.ts +74 -0
- package/src/agents/researcher.ts +43 -0
- package/src/config.ts +168 -0
- package/src/index.ts +152 -0
- package/src/installer.ts +130 -0
- package/src/orchestrator/arena.ts +41 -0
- package/src/orchestrator/artifacts.ts +28 -0
- package/src/orchestrator/confidence.ts +59 -0
- package/src/orchestrator/fallback/chat-message-handler.ts +49 -0
- package/src/orchestrator/fallback/error-classifier.ts +148 -0
- package/src/orchestrator/fallback/event-handler.ts +235 -0
- package/src/orchestrator/fallback/fallback-config.ts +16 -0
- package/src/orchestrator/fallback/fallback-manager.ts +323 -0
- package/src/orchestrator/fallback/fallback-state.ts +120 -0
- package/src/orchestrator/fallback/index.ts +11 -0
- package/src/orchestrator/fallback/message-replay.ts +40 -0
- package/src/orchestrator/fallback/resolve-chain.ts +34 -0
- package/src/orchestrator/fallback/tool-execute-handler.ts +44 -0
- package/src/orchestrator/fallback/types.ts +46 -0
- package/src/orchestrator/handlers/architect.ts +114 -0
- package/src/orchestrator/handlers/build.ts +363 -0
- package/src/orchestrator/handlers/challenge.ts +41 -0
- package/src/orchestrator/handlers/explore.ts +9 -0
- package/src/orchestrator/handlers/index.ts +21 -0
- package/src/orchestrator/handlers/plan.ts +35 -0
- package/src/orchestrator/handlers/recon.ts +40 -0
- package/src/orchestrator/handlers/retrospective.ts +123 -0
- package/src/orchestrator/handlers/ship.ts +38 -0
- package/src/orchestrator/handlers/types.ts +31 -0
- package/src/orchestrator/lesson-injection.ts +80 -0
- package/src/orchestrator/lesson-memory.ts +110 -0
- package/src/orchestrator/lesson-schemas.ts +24 -0
- package/src/orchestrator/lesson-types.ts +6 -0
- package/src/orchestrator/phase.ts +76 -0
- package/src/orchestrator/plan.ts +43 -0
- package/src/orchestrator/schemas.ts +86 -0
- package/src/orchestrator/skill-injection.ts +52 -0
- package/src/orchestrator/state.ts +80 -0
- package/src/orchestrator/types.ts +20 -0
- package/src/review/agent-catalog.ts +439 -0
- package/src/review/agents/auth-flow-verifier.ts +47 -0
- package/src/review/agents/code-quality-auditor.ts +51 -0
- package/src/review/agents/concurrency-checker.ts +47 -0
- package/src/review/agents/contract-verifier.ts +45 -0
- package/src/review/agents/database-auditor.ts +47 -0
- package/src/review/agents/dead-code-scanner.ts +47 -0
- package/src/review/agents/go-idioms-auditor.ts +46 -0
- package/src/review/agents/index.ts +82 -0
- package/src/review/agents/logic-auditor.ts +47 -0
- package/src/review/agents/product-thinker.ts +49 -0
- package/src/review/agents/python-django-auditor.ts +46 -0
- package/src/review/agents/react-patterns-auditor.ts +46 -0
- package/src/review/agents/red-team.ts +49 -0
- package/src/review/agents/rust-safety-auditor.ts +46 -0
- package/src/review/agents/scope-intent-verifier.ts +45 -0
- package/src/review/agents/security-auditor.ts +47 -0
- package/src/review/agents/silent-failure-hunter.ts +45 -0
- package/src/review/agents/spec-checker.ts +45 -0
- package/src/review/agents/state-mgmt-auditor.ts +46 -0
- package/src/review/agents/test-interrogator.ts +43 -0
- package/src/review/agents/type-soundness.ts +46 -0
- package/src/review/agents/wiring-inspector.ts +46 -0
- package/src/review/cross-verification.ts +71 -0
- package/src/review/finding-builder.ts +74 -0
- package/src/review/fix-cycle.ts +146 -0
- package/src/review/memory.ts +114 -0
- package/src/review/pipeline.ts +258 -0
- package/src/review/report.ts +141 -0
- package/src/review/sanitize.ts +8 -0
- package/src/review/schemas.ts +75 -0
- package/src/review/selection.ts +98 -0
- package/src/review/severity.ts +71 -0
- package/src/review/stack-gate.ts +127 -0
- package/src/review/types.ts +43 -0
- package/src/templates/agent-template.ts +47 -0
- package/src/templates/command-template.ts +29 -0
- package/src/templates/skill-template.ts +42 -0
- package/src/tools/confidence.ts +93 -0
- package/src/tools/create-agent.ts +81 -0
- package/src/tools/create-command.ts +74 -0
- package/src/tools/create-skill.ts +74 -0
- package/src/tools/forensics.ts +88 -0
- package/src/tools/orchestrate.ts +310 -0
- package/src/tools/phase.ts +92 -0
- package/src/tools/placeholder.ts +11 -0
- package/src/tools/plan.ts +56 -0
- package/src/tools/review.ts +295 -0
- package/src/tools/state.ts +112 -0
- package/src/utils/fs-helpers.ts +39 -0
- package/src/utils/gitignore.ts +27 -0
- package/src/utils/paths.ts +17 -0
- package/src/utils/validators.ts +57 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 kodrunhq
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# @kodrunhq/opencode-autopilot
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: A placeholder agent installed by opencode-autopilot to verify the plugin is working
|
|
3
|
+
mode: all
|
|
4
|
+
permission:
|
|
5
|
+
read: allow
|
|
6
|
+
edit: deny
|
|
7
|
+
bash: deny
|
|
8
|
+
webfetch: deny
|
|
9
|
+
task: deny
|
|
10
|
+
---
|
|
11
|
+
You are a placeholder agent installed by the opencode-autopilot plugin. Your purpose is to confirm the plugin's asset installation is working correctly.
|
|
12
|
+
|
|
13
|
+
When invoked, explain that you are a placeholder and suggest the user explore other agents provided by the opencode-autopilot plugin.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Configure the opencode-autopilot plugin -- assign models to agents
|
|
3
|
+
---
|
|
4
|
+
The opencode-autopilot plugin supports configuration for model mapping. You can assign specific models to each agent provided by the plugin by editing the config file at `~/.config/opencode/opencode-autopilot.json`.
|
|
5
|
+
|
|
6
|
+
The config file uses this format:
|
|
7
|
+
```json
|
|
8
|
+
{
|
|
9
|
+
"version": 1,
|
|
10
|
+
"configured": true,
|
|
11
|
+
"models": {
|
|
12
|
+
"agent-name": "provider/model-id"
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Note: An interactive configuration tool will be added in a future phase to automate this process.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Create a new OpenCode agent from within this session
|
|
3
|
+
---
|
|
4
|
+
The user wants to create a new OpenCode agent. Gather the following information conversationally before calling the tool:
|
|
5
|
+
|
|
6
|
+
1. **name** (required): Agent name in lowercase with hyphens (e.g., "code-reviewer", "test-helper"). Must be 1-64 characters, alphanumeric with hyphens only.
|
|
7
|
+
2. **description** (required): A clear description of what the agent does (max 500 characters).
|
|
8
|
+
3. **mode** (optional, default: "subagent"): One of "primary" (main agent), "subagent" (invoked via @mention), or "all" (both).
|
|
9
|
+
4. **model** (optional): Model identifier to use (e.g., "anthropic/claude-sonnet-4-20250514"). Omit for model-agnostic agents.
|
|
10
|
+
5. **temperature** (optional): Temperature setting from 0.0 to 1.0. Omit for default.
|
|
11
|
+
|
|
12
|
+
Once you have all the required information, call the `oc_create_agent` tool with the collected parameters. The tool will validate the name, generate the agent file, and write it to the correct location.
|
|
13
|
+
|
|
14
|
+
After creation, remind the user to restart OpenCode and suggest they edit the generated file to customize the system prompt.
|
|
15
|
+
|
|
16
|
+
$ARGUMENTS
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Create a new OpenCode command from within this session
|
|
3
|
+
---
|
|
4
|
+
The user wants to create a new OpenCode slash command. Gather the following information conversationally before calling the tool:
|
|
5
|
+
|
|
6
|
+
1. **name** (required): Command name in lowercase with hyphens (e.g., "review", "deploy-check"). Must be 1-64 characters, alphanumeric with hyphens only. Cannot conflict with built-in commands (init, undo, redo, share, help, config, compact, clear, cost, login, logout, bug).
|
|
7
|
+
2. **description** (required): A clear description of what the command does when invoked (max 500 characters).
|
|
8
|
+
3. **agent** (optional): Agent to use when running this command (e.g., "code-reviewer").
|
|
9
|
+
4. **model** (optional): Model override for this command.
|
|
10
|
+
|
|
11
|
+
Once you have all the required information, call the `oc_create_command` tool with the collected parameters. The tool will validate the name, generate the command file, and write it to the correct location.
|
|
12
|
+
|
|
13
|
+
After creation, remind the user to restart OpenCode and suggest they edit the generated file to customize the command instructions. Mention that they can use `$ARGUMENTS` for user input and `@filename` to include file content.
|
|
14
|
+
|
|
15
|
+
$ARGUMENTS
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Create a new OpenCode skill from within this session
|
|
3
|
+
---
|
|
4
|
+
The user wants to create a new OpenCode skill. Gather the following information conversationally before calling the tool:
|
|
5
|
+
|
|
6
|
+
1. **name** (required): Skill name in lowercase with hyphens (e.g., "typescript-patterns", "api-design"). Must be 1-64 characters, alphanumeric with hyphens only.
|
|
7
|
+
2. **description** (required): A clear description of what the skill provides to the AI agent (max 1024 characters).
|
|
8
|
+
3. **license** (optional): License for the skill (e.g., "MIT").
|
|
9
|
+
4. **compatibility** (optional): Compatibility target (e.g., "opencode").
|
|
10
|
+
|
|
11
|
+
Once you have all the required information, call the `oc_create_skill` tool with the collected parameters. The tool will validate the name, create the skill directory, and write the SKILL.md file.
|
|
12
|
+
|
|
13
|
+
After creation, remind the user to restart OpenCode and suggest they edit the generated SKILL.md to add domain knowledge, rules, and examples.
|
|
14
|
+
|
|
15
|
+
$ARGUMENTS
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Review a GitHub PR with structured, actionable feedback
|
|
3
|
+
agent: pr-reviewer
|
|
4
|
+
---
|
|
5
|
+
Review the pull request specified by $ARGUMENTS.
|
|
6
|
+
|
|
7
|
+
Before running any commands, validate that $ARGUMENTS is a valid PR identifier (a number or a URL). If it contains shell metacharacters or does not look like a PR reference, ask the user to provide a valid PR number.
|
|
8
|
+
|
|
9
|
+
First, gather the PR context:
|
|
10
|
+
|
|
11
|
+
1. Run `gh pr view $ARGUMENTS` to get the PR title, description, author, and status
|
|
12
|
+
2. Run `gh pr diff $ARGUMENTS` to get the full diff
|
|
13
|
+
3. If the diff is large, run `gh pr diff $ARGUMENTS --name-only` first to identify changed files, then review them in logical groups
|
|
14
|
+
|
|
15
|
+
Then analyze the PR against these dimensions:
|
|
16
|
+
|
|
17
|
+
- **Correctness:** Does the code do what the PR description claims? Are there logic errors, off-by-one bugs, or missing edge cases?
|
|
18
|
+
- **Security:** Are there hardcoded secrets, unsanitized inputs, missing auth checks, or injection vulnerabilities?
|
|
19
|
+
- **Code quality:** Does the code follow the coding-standards skill? Check naming, file size, function size, error handling, immutability, and separation of concerns.
|
|
20
|
+
- **Testing:** Are there tests for new functionality? Do existing tests still cover the changed code paths?
|
|
21
|
+
- **Performance:** Are there N+1 queries, unnecessary allocations, missing indexes, or unbounded loops?
|
|
22
|
+
|
|
23
|
+
Provide your review in this structure:
|
|
24
|
+
|
|
25
|
+
## Summary
|
|
26
|
+
|
|
27
|
+
What the PR does in 2-3 sentences.
|
|
28
|
+
|
|
29
|
+
## Findings
|
|
30
|
+
|
|
31
|
+
List issues by severity. For each finding, include the file, line range, what is wrong, and a suggested fix.
|
|
32
|
+
|
|
33
|
+
- **CRITICAL** -- Must fix before merge (security vulnerabilities, data loss, crashes)
|
|
34
|
+
- **HIGH** -- Should fix before merge (logic errors, missing error handling, broken edge cases)
|
|
35
|
+
- **MEDIUM** -- Consider fixing (code quality, naming, minor refactoring opportunities)
|
|
36
|
+
- **LOW** -- Nit-level suggestions (style, optional improvements)
|
|
37
|
+
|
|
38
|
+
If no issues are found at a severity level, omit that level.
|
|
39
|
+
|
|
40
|
+
## Positive Notes
|
|
41
|
+
|
|
42
|
+
What the PR does well -- good patterns, clean abstractions, thorough tests.
|
|
43
|
+
|
|
44
|
+
## Verdict
|
|
45
|
+
|
|
46
|
+
One of:
|
|
47
|
+
- **APPROVE** -- No critical or high issues. Ready to merge.
|
|
48
|
+
- **REQUEST_CHANGES** -- Has critical or high issues that must be addressed.
|
|
49
|
+
- **NEEDS_DISCUSSION** -- Architectural or design concerns that need team input.
|
|
File without changes
|
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: coding-standards
|
|
3
|
+
description: Universal coding standards and best practices for code review and generation. Covers naming, file organization, error handling, immutability, and separation of concerns.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Coding Standards
|
|
7
|
+
|
|
8
|
+
Universal, language-agnostic coding standards. Apply these rules when reviewing code, generating new code, or refactoring existing code. Every rule is opinionated and actionable.
|
|
9
|
+
|
|
10
|
+
## 1. Naming Conventions
|
|
11
|
+
|
|
12
|
+
**DO:** Use descriptive, intention-revealing names. Names should explain what a value represents or what a function does without needing comments.
|
|
13
|
+
|
|
14
|
+
- Variables: nouns that describe the value (`userCount`, `activeOrders`, `maxRetries`)
|
|
15
|
+
- Functions: verbs that describe the action (`fetchUser`, `calculateTotal`, `validateInput`)
|
|
16
|
+
- Booleans: questions that read naturally (`isActive`, `hasPermission`, `shouldRetry`, `canEdit`)
|
|
17
|
+
- Constants: UPPER_SNAKE_CASE for true constants (`MAX_RETRIES`, `DEFAULT_TIMEOUT`)
|
|
18
|
+
- Use consistent casing per convention: camelCase for variables/functions, PascalCase for types/classes
|
|
19
|
+
|
|
20
|
+
**DON'T:**
|
|
21
|
+
|
|
22
|
+
- Use single-letter variables outside of trivial loops (`x`, `d`, `t`)
|
|
23
|
+
- Use abbreviations that are not universally understood (`usr`, `mgr`, `btn`, `cfg`)
|
|
24
|
+
- Use generic names that convey no meaning (`data`, `info`, `temp`, `stuff`, `result`)
|
|
25
|
+
- Use negated booleans (`isNotValid` -- use `isValid` and negate at the call site)
|
|
26
|
+
- Encode types in names (`strName`, `arrItems`, `iCount`)
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
// DO
|
|
30
|
+
remainingAttempts = maxRetries - failedAttempts
|
|
31
|
+
isEligibleForDiscount = orderTotal > minimumThreshold
|
|
32
|
+
|
|
33
|
+
// DON'T
|
|
34
|
+
x = r - f
|
|
35
|
+
flag = t > m
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## 2. File Organization
|
|
39
|
+
|
|
40
|
+
**DO:** Keep files focused on a single concern. One module should do one thing well.
|
|
41
|
+
|
|
42
|
+
- Target 200-400 lines per file. Hard maximum of 800 lines.
|
|
43
|
+
- Organize by feature or domain, not by file type (group `user/` together, not `controllers/` + `models/` + `services/`)
|
|
44
|
+
- Place related files close together in the directory tree
|
|
45
|
+
- One exported class or primary function per file
|
|
46
|
+
- Index files (barrel exports) for public API surfaces only
|
|
47
|
+
|
|
48
|
+
**DON'T:**
|
|
49
|
+
|
|
50
|
+
- Mix unrelated functionality in a single file
|
|
51
|
+
- Create files with multiple independent classes or modules
|
|
52
|
+
- Nest directories more than 4 levels deep
|
|
53
|
+
- Put all utilities in a single `utils.ts` grab-bag file
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
// DO: Organize by feature
|
|
57
|
+
user/
|
|
58
|
+
create-user.ts
|
|
59
|
+
validate-user.ts
|
|
60
|
+
user-repository.ts
|
|
61
|
+
user.test.ts
|
|
62
|
+
|
|
63
|
+
// DON'T: Organize by type
|
|
64
|
+
controllers/
|
|
65
|
+
user-controller.ts
|
|
66
|
+
order-controller.ts
|
|
67
|
+
services/
|
|
68
|
+
user-service.ts
|
|
69
|
+
order-service.ts
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## 3. Function Design
|
|
73
|
+
|
|
74
|
+
**DO:** Write small functions that do exactly one thing.
|
|
75
|
+
|
|
76
|
+
- Target under 50 lines per function. If longer, extract sub-functions.
|
|
77
|
+
- Maximum 3-4 levels of nesting. Extract nested logic into named functions.
|
|
78
|
+
- Limit parameters to 3. Use an options object for more.
|
|
79
|
+
- Return early for guard clauses and error conditions.
|
|
80
|
+
- Pure functions where possible -- same input always produces same output.
|
|
81
|
+
|
|
82
|
+
**DON'T:**
|
|
83
|
+
|
|
84
|
+
- Write functions that handle multiple unrelated responsibilities
|
|
85
|
+
- Use deeply nested if/else chains or switch statements with complex logic
|
|
86
|
+
- Pass boolean flags that change behavior (`processOrder(order, true, false)`)
|
|
87
|
+
- Rely on side effects that are not obvious from the function name
|
|
88
|
+
|
|
89
|
+
```
|
|
90
|
+
// DO: Early return for guard clauses
|
|
91
|
+
function getDiscount(customer) {
|
|
92
|
+
if (!customer) return 0
|
|
93
|
+
if (!customer.isActive) return 0
|
|
94
|
+
if (customer.orders < 10) return 0.05
|
|
95
|
+
return 0.15
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// DON'T: Deep nesting
|
|
99
|
+
function getDiscount(customer) {
|
|
100
|
+
if (customer) {
|
|
101
|
+
if (customer.isActive) {
|
|
102
|
+
if (customer.orders >= 10) {
|
|
103
|
+
return 0.15
|
|
104
|
+
} else {
|
|
105
|
+
return 0.05
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return 0
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## 4. Error Handling
|
|
114
|
+
|
|
115
|
+
**DO:** Handle errors explicitly at every level. Every error path deserves deliberate treatment.
|
|
116
|
+
|
|
117
|
+
- Catch errors as close to the source as possible
|
|
118
|
+
- Provide user-friendly messages in UI-facing code
|
|
119
|
+
- Log detailed context (operation, input values, stack) on the server side
|
|
120
|
+
- Use typed or domain-specific error classes to distinguish error categories
|
|
121
|
+
- Fail fast -- validate inputs before processing
|
|
122
|
+
|
|
123
|
+
**DON'T:**
|
|
124
|
+
|
|
125
|
+
- Silently swallow errors with empty catch blocks
|
|
126
|
+
- Use exceptions for control flow (expected conditions should use return values)
|
|
127
|
+
- Expose internal error details (stack traces, SQL queries) to end users
|
|
128
|
+
- Log errors without enough context to reproduce the issue
|
|
129
|
+
- Catch generic exceptions when you can catch specific ones
|
|
130
|
+
|
|
131
|
+
```
|
|
132
|
+
// DO: Explicit handling with context
|
|
133
|
+
try {
|
|
134
|
+
user = await fetchUser(userId)
|
|
135
|
+
} catch (error) {
|
|
136
|
+
logger.error("Failed to fetch user", { userId, error })
|
|
137
|
+
throw new UserNotFoundError(userId)
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// DON'T: Silent swallow
|
|
141
|
+
try {
|
|
142
|
+
user = await fetchUser(userId)
|
|
143
|
+
} catch (error) {
|
|
144
|
+
// ignore
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## 5. Immutability
|
|
149
|
+
|
|
150
|
+
**DO:** Create new objects instead of mutating existing ones. Immutable data prevents hidden side effects and makes code easier to reason about.
|
|
151
|
+
|
|
152
|
+
- Use spread operators, `map`, `filter`, `reduce` to derive new values
|
|
153
|
+
- Treat function arguments as read-only
|
|
154
|
+
- Use `readonly` modifiers or frozen objects where the language supports it
|
|
155
|
+
- Return new objects from update functions
|
|
156
|
+
|
|
157
|
+
**DON'T:**
|
|
158
|
+
|
|
159
|
+
- Reassign function parameters
|
|
160
|
+
- Use `push`, `splice`, `pop` on arrays shared across boundaries
|
|
161
|
+
- Modify objects passed into a function from the caller's scope
|
|
162
|
+
- Use mutable global state
|
|
163
|
+
|
|
164
|
+
**Exception:** Mutation is acceptable when an API explicitly requires it (e.g., OpenCode config hooks, database transaction builders, stream writers).
|
|
165
|
+
|
|
166
|
+
```
|
|
167
|
+
// DO: Return new object
|
|
168
|
+
function addItem(cart, item) {
|
|
169
|
+
return {
|
|
170
|
+
...cart,
|
|
171
|
+
items: [...cart.items, item],
|
|
172
|
+
total: cart.total + item.price,
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// DON'T: Mutate in place
|
|
177
|
+
function addItem(cart, item) {
|
|
178
|
+
cart.items.push(item)
|
|
179
|
+
cart.total += item.price
|
|
180
|
+
return cart
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
## 6. Separation of Concerns
|
|
185
|
+
|
|
186
|
+
**DO:** Keep distinct responsibilities in distinct layers. Each layer should be independently testable.
|
|
187
|
+
|
|
188
|
+
- Data access (repositories, API clients) separate from business logic
|
|
189
|
+
- Business logic separate from presentation and formatting
|
|
190
|
+
- Define interfaces at layer boundaries
|
|
191
|
+
- Infrastructure concerns (logging, caching, auth) as cross-cutting middleware, not inline code
|
|
192
|
+
|
|
193
|
+
**DON'T:**
|
|
194
|
+
|
|
195
|
+
- Mix HTTP/request handling with business rules
|
|
196
|
+
- Put database queries inside UI rendering code
|
|
197
|
+
- Scatter validation logic across multiple layers (validate once at the boundary)
|
|
198
|
+
- Hard-code infrastructure dependencies inside business logic
|
|
199
|
+
|
|
200
|
+
```
|
|
201
|
+
// DO: Layered
|
|
202
|
+
orderRepository.save(order) // data access
|
|
203
|
+
orderService.calculateTotal(order) // business logic
|
|
204
|
+
orderView.formatSummary(order) // presentation
|
|
205
|
+
|
|
206
|
+
// DON'T: Mixed concerns
|
|
207
|
+
function handleOrderRequest(req, res) {
|
|
208
|
+
db.query("INSERT INTO orders ...") // data access in handler
|
|
209
|
+
total = items.reduce(...) // business logic in handler
|
|
210
|
+
res.send("<h1>" + total + "</h1>") // presentation in handler
|
|
211
|
+
}
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
## 7. DRY (Don't Repeat Yourself)
|
|
215
|
+
|
|
216
|
+
**DO:** Extract shared logic when you see the same pattern duplicated 3 or more times.
|
|
217
|
+
|
|
218
|
+
- Create utility functions for repeated operations
|
|
219
|
+
- Use composition to share behavior between modules
|
|
220
|
+
- Centralize constants and configuration values
|
|
221
|
+
|
|
222
|
+
**DON'T:**
|
|
223
|
+
|
|
224
|
+
- Over-abstract before duplication exists (YAGNI -- You Aren't Gonna Need It)
|
|
225
|
+
- Create abstractions for things that are only superficially similar
|
|
226
|
+
- Use inheritance as the primary mechanism for code reuse (prefer composition)
|
|
227
|
+
- Extract "shared" code that is actually used in only one place
|
|
228
|
+
|
|
229
|
+
```
|
|
230
|
+
// DO: Extract after 3+ duplications
|
|
231
|
+
function formatCurrency(amount, currency) {
|
|
232
|
+
return `${currencySymbol(currency)}${amount.toFixed(2)}`
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// DON'T: Premature abstraction
|
|
236
|
+
// Creating a CurrencyFormatterFactory when you have one format
|
|
237
|
+
class CurrencyFormatterFactory {
|
|
238
|
+
create(locale, options) { ... }
|
|
239
|
+
}
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
## 8. Input Validation
|
|
243
|
+
|
|
244
|
+
**DO:** Validate all external data at system boundaries. Never trust input from users, APIs, files, or environment variables.
|
|
245
|
+
|
|
246
|
+
- Use schema-based validation (Zod, JSON Schema, etc.) for structured input
|
|
247
|
+
- Validate as early as possible -- fail fast with clear error messages
|
|
248
|
+
- Sanitize strings that will be used in HTML, SQL, or shell commands
|
|
249
|
+
- Define allowed values explicitly (allowlists over blocklists)
|
|
250
|
+
|
|
251
|
+
**DON'T:**
|
|
252
|
+
|
|
253
|
+
- Trust external data without validation
|
|
254
|
+
- Validate deep inside business logic instead of at the boundary
|
|
255
|
+
- Use blocklists for security-sensitive input (always use allowlists)
|
|
256
|
+
- Accept arbitrary types and check with `typeof` throughout the code
|
|
257
|
+
|
|
258
|
+
```
|
|
259
|
+
// DO: Schema validation at boundary
|
|
260
|
+
schema = object({
|
|
261
|
+
email: string().email(),
|
|
262
|
+
age: number().int().min(0).max(150),
|
|
263
|
+
})
|
|
264
|
+
validated = schema.parse(requestBody)
|
|
265
|
+
|
|
266
|
+
// DON'T: Ad-hoc checks scattered everywhere
|
|
267
|
+
if (typeof input.email === "string" && input.email.includes("@")) {
|
|
268
|
+
if (typeof input.age === "number" && input.age > 0) {
|
|
269
|
+
// ... buried validation
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
## 9. Constants and Configuration
|
|
275
|
+
|
|
276
|
+
**DO:** Use named constants and configuration files for values that may change or carry meaning.
|
|
277
|
+
|
|
278
|
+
- Named constants for magic numbers and strings (`MAX_RETRIES = 3`, not just `3`)
|
|
279
|
+
- Environment variables or config files for deployment-specific values
|
|
280
|
+
- Group related constants in a dedicated module
|
|
281
|
+
- Document units in constant names (`TIMEOUT_MS = 5000`, `MAX_FILE_SIZE_BYTES = 10485760`)
|
|
282
|
+
|
|
283
|
+
**DON'T:**
|
|
284
|
+
|
|
285
|
+
- Hardcode URLs, API keys, timeouts, or limits in application code
|
|
286
|
+
- Use magic numbers without explanation (`if (retries > 3)` -- why 3?)
|
|
287
|
+
- Store secrets in source code or config files committed to version control
|
|
288
|
+
- Scatter the same constant value across multiple files
|
|
289
|
+
|
|
290
|
+
```
|
|
291
|
+
// DO: Named constants with units
|
|
292
|
+
CACHE_TTL_SECONDS = 300
|
|
293
|
+
MAX_UPLOAD_SIZE_BYTES = 10 * 1024 * 1024
|
|
294
|
+
API_BASE_URL = config.get("api.baseUrl")
|
|
295
|
+
|
|
296
|
+
// DON'T: Magic values
|
|
297
|
+
setTimeout(callback, 300000)
|
|
298
|
+
if (file.size > 10485760) { ... }
|
|
299
|
+
fetch("https://api.example.com/v2/users")
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
## 10. Code Comments
|
|
303
|
+
|
|
304
|
+
**DO:** Comment the WHY, not the WHAT. Code should be readable enough that the "what" is obvious. Comments explain intent, trade-offs, and non-obvious decisions.
|
|
305
|
+
|
|
306
|
+
- Explain why a non-obvious approach was chosen over the obvious one
|
|
307
|
+
- Document edge cases and their handling rationale
|
|
308
|
+
- Use JSDoc/docstrings for public API surfaces (parameters, return values, exceptions)
|
|
309
|
+
- Mark temporary workarounds with `TODO(reason):` and a tracking reference
|
|
310
|
+
|
|
311
|
+
**DON'T:**
|
|
312
|
+
|
|
313
|
+
- Write comments that restate what the code does (`// increment counter` above `counter++`)
|
|
314
|
+
- Leave commented-out code in the codebase (use version control instead)
|
|
315
|
+
- Write comments that will become stale when the code changes
|
|
316
|
+
- Use comments as a substitute for clear naming and structure
|
|
317
|
+
|
|
318
|
+
```
|
|
319
|
+
// DO: Explain why
|
|
320
|
+
// Rate limit is 100/min per API docs. We use 80 to leave headroom
|
|
321
|
+
// for background jobs that share the same API key.
|
|
322
|
+
MAX_REQUESTS_PER_MINUTE = 80
|
|
323
|
+
|
|
324
|
+
// DON'T: Restate the code
|
|
325
|
+
// Set the max requests to 80
|
|
326
|
+
MAX_REQUESTS_PER_MINUTE = 80
|
|
327
|
+
```
|
package/package.json
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@kodrunhq/opencode-autopilot",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Curated agents, skills, and commands for the OpenCode AI coding CLI — autonomous orchestrator, multi-agent code review, model fallback, and in-session asset creation tools.",
|
|
5
|
+
"main": "src/index.ts",
|
|
6
|
+
"keywords": [
|
|
7
|
+
"opencode",
|
|
8
|
+
"opencode-plugin",
|
|
9
|
+
"ai",
|
|
10
|
+
"agents",
|
|
11
|
+
"code-review",
|
|
12
|
+
"orchestrator",
|
|
13
|
+
"model-fallback"
|
|
14
|
+
],
|
|
15
|
+
"license": "MIT",
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "git+https://github.com/kodrunhq/opencode-autopilot.git"
|
|
19
|
+
},
|
|
20
|
+
"homepage": "https://github.com/kodrunhq/opencode-autopilot#readme",
|
|
21
|
+
"bugs": {
|
|
22
|
+
"url": "https://github.com/kodrunhq/opencode-autopilot/issues"
|
|
23
|
+
},
|
|
24
|
+
"author": "kodrunhq",
|
|
25
|
+
"publishConfig": {
|
|
26
|
+
"access": "public",
|
|
27
|
+
"provenance": true
|
|
28
|
+
},
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"@biomejs/biome": "^2.4.10",
|
|
31
|
+
"@opencode-ai/plugin": "^1.3.8",
|
|
32
|
+
"@types/bun": "^1.3.11",
|
|
33
|
+
"typescript": "^6.0.2"
|
|
34
|
+
},
|
|
35
|
+
"peerDependencies": {
|
|
36
|
+
"@opencode-ai/plugin": ">=1.3.0"
|
|
37
|
+
},
|
|
38
|
+
"files": [
|
|
39
|
+
"src/",
|
|
40
|
+
"assets/"
|
|
41
|
+
],
|
|
42
|
+
"scripts": {
|
|
43
|
+
"test": "bun test",
|
|
44
|
+
"lint": "biome check .",
|
|
45
|
+
"format": "biome format . --write",
|
|
46
|
+
"prepublishOnly": "bun test && bunx tsc --noEmit"
|
|
47
|
+
},
|
|
48
|
+
"type": "module",
|
|
49
|
+
"dependencies": {
|
|
50
|
+
"yaml": "^2.8.3"
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { AgentConfig } from "@opencode-ai/sdk";
|
|
2
|
+
|
|
3
|
+
export const autopilotAgent: Readonly<AgentConfig> = Object.freeze({
|
|
4
|
+
description:
|
|
5
|
+
"Tell me what to build and I'll handle research, architecture, planning, implementation, review, and delivery -- fully autonomous.",
|
|
6
|
+
mode: "all",
|
|
7
|
+
maxSteps: 50,
|
|
8
|
+
prompt: `You are the autopilot agent. You drive a multi-phase SDLC pipeline using the oc_orchestrate tool.
|
|
9
|
+
|
|
10
|
+
## Loop
|
|
11
|
+
|
|
12
|
+
1. Call oc_orchestrate with your initial idea (first turn) or with the result from the previous agent.
|
|
13
|
+
2. Parse the JSON response.
|
|
14
|
+
3. If action is "dispatch": call the named agent with the provided prompt, then pass its output back to oc_orchestrate via the result parameter.
|
|
15
|
+
4. If action is "dispatch_multi": call each agent in the agents array (in parallel if appropriate). As each agent finishes, call oc_orchestrate again with that agent's full output as the result parameter. Do NOT combine multiple agents' outputs into a single result.
|
|
16
|
+
5. If action is "complete": report the summary to the user. You are done.
|
|
17
|
+
6. If action is "error": report the error to the user. Stop.
|
|
18
|
+
|
|
19
|
+
## Rules
|
|
20
|
+
|
|
21
|
+
- NEVER skip calling oc_orchestrate. It is the single source of truth for pipeline state.
|
|
22
|
+
- NEVER make pipeline decisions yourself. Always defer to oc_orchestrate.
|
|
23
|
+
- ALWAYS pass the full agent output back as the result parameter.
|
|
24
|
+
- Do not attempt to run phases out of order.
|
|
25
|
+
- Do not retry a failed phase unless oc_orchestrate instructs you to.
|
|
26
|
+
- If an agent dispatch fails, pass the error message back to oc_orchestrate as the result.
|
|
27
|
+
|
|
28
|
+
## Example Turn Sequence
|
|
29
|
+
|
|
30
|
+
Turn 1: oc_orchestrate(idea="Build a CLI tool")
|
|
31
|
+
-> {action:"dispatch", agent:"oc-researcher", prompt:"Research: Build a CLI tool", phase:"RECON"}
|
|
32
|
+
Turn 2: @oc-researcher "Research: Build a CLI tool"
|
|
33
|
+
-> "Research findings: ..."
|
|
34
|
+
Turn 3: oc_orchestrate(result="Research findings: ...")
|
|
35
|
+
-> {action:"dispatch", agent:"oc-challenger", prompt:"Challenge: ...", phase:"CHALLENGE"}
|
|
36
|
+
... continues until action is "complete"`,
|
|
37
|
+
permission: {
|
|
38
|
+
edit: "allow",
|
|
39
|
+
bash: "allow",
|
|
40
|
+
webfetch: "allow",
|
|
41
|
+
} as const,
|
|
42
|
+
});
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { AgentConfig } from "@opencode-ai/sdk";
|
|
2
|
+
|
|
3
|
+
export const documenterAgent: Readonly<AgentConfig> = Object.freeze({
|
|
4
|
+
description:
|
|
5
|
+
"Creates and maintains documentation, READMEs, architecture diagrams, and developer guides",
|
|
6
|
+
mode: "subagent",
|
|
7
|
+
prompt: `You are a technical documentation specialist. Your job is to create polished, comprehensive documentation for codebases and projects.
|
|
8
|
+
|
|
9
|
+
## Instructions
|
|
10
|
+
|
|
11
|
+
1. Read the codebase to understand the project structure, public APIs, and conventions.
|
|
12
|
+
2. Reference the coding-standards skill at ~/.config/opencode/skills/coding-standards/SKILL.md for conventions when documenting code patterns and style guidelines.
|
|
13
|
+
3. Generate documentation that is accurate, well-organized, and immediately useful to developers.
|
|
14
|
+
4. Create or edit documentation files directly — you have permission to modify existing docs.
|
|
15
|
+
|
|
16
|
+
## Capabilities
|
|
17
|
+
|
|
18
|
+
You can produce any of the following:
|
|
19
|
+
|
|
20
|
+
- **README files** — project overview, installation, usage, contributing guidelines.
|
|
21
|
+
- **Architecture documents** — system design, component relationships, data flow using Mermaid diagrams.
|
|
22
|
+
- **API documentation** — endpoint references, type definitions, usage examples.
|
|
23
|
+
- **Developer guides** — quickstart tutorials, setup instructions, troubleshooting.
|
|
24
|
+
- **GitHub badges** — shields.io badge markdown for CI status, version, license, coverage.
|
|
25
|
+
- **Changelogs** — structured release notes following Keep a Changelog format.
|
|
26
|
+
|
|
27
|
+
## Output Format
|
|
28
|
+
|
|
29
|
+
Write documentation as polished markdown. Use headings, lists, code blocks, tables, and Mermaid diagram blocks as appropriate. Documentation should be ready to commit without further editing.
|
|
30
|
+
|
|
31
|
+
## Constraints
|
|
32
|
+
|
|
33
|
+
- DO read source code thoroughly before writing documentation — accuracy is paramount.
|
|
34
|
+
- DO reference existing conventions and coding-standards for consistency.
|
|
35
|
+
- DO create new files or edit existing documentation files as needed.
|
|
36
|
+
- DO NOT run shell commands.
|
|
37
|
+
- DO NOT access the web.
|
|
38
|
+
- DO NOT modify source code files — only documentation files (.md, .txt, diagrams).`,
|
|
39
|
+
permission: {
|
|
40
|
+
edit: "allow",
|
|
41
|
+
bash: "deny",
|
|
42
|
+
webfetch: "deny",
|
|
43
|
+
} as const,
|
|
44
|
+
});
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { Config } from "@opencode-ai/plugin";
|
|
2
|
+
import { autopilotAgent } from "./autopilot";
|
|
3
|
+
import { documenterAgent } from "./documenter";
|
|
4
|
+
import { metaprompterAgent } from "./metaprompter";
|
|
5
|
+
import { pipelineAgents } from "./pipeline/index";
|
|
6
|
+
import { prReviewerAgent } from "./pr-reviewer";
|
|
7
|
+
import { researcherAgent } from "./researcher";
|
|
8
|
+
|
|
9
|
+
const agents = {
|
|
10
|
+
researcher: researcherAgent,
|
|
11
|
+
metaprompter: metaprompterAgent,
|
|
12
|
+
documenter: documenterAgent,
|
|
13
|
+
"pr-reviewer": prReviewerAgent,
|
|
14
|
+
autopilot: autopilotAgent,
|
|
15
|
+
} as const;
|
|
16
|
+
|
|
17
|
+
export async function configHook(config: Config): Promise<void> {
|
|
18
|
+
if (!config.agent) {
|
|
19
|
+
config.agent = {};
|
|
20
|
+
}
|
|
21
|
+
for (const [name, agentConfig] of Object.entries(agents)) {
|
|
22
|
+
// Only set if not already defined — preserve user customizations (Pitfall 2)
|
|
23
|
+
if (config.agent[name] === undefined) {
|
|
24
|
+
// Mutation of config.agent is intentional: the OpenCode plugin configHook
|
|
25
|
+
// API requires mutating the provided Config object to register agents.
|
|
26
|
+
// We deep-copy agent config including nested permission to avoid shared references.
|
|
27
|
+
config.agent[name] = {
|
|
28
|
+
...agentConfig,
|
|
29
|
+
...(agentConfig.permission && { permission: { ...agentConfig.permission } }),
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Register pipeline agents (v2 orchestrator subagents)
|
|
35
|
+
for (const [name, agentConfig] of Object.entries(pipelineAgents)) {
|
|
36
|
+
if (config.agent[name] === undefined) {
|
|
37
|
+
config.agent[name] = {
|
|
38
|
+
...agentConfig,
|
|
39
|
+
...(agentConfig.permission && { permission: { ...agentConfig.permission } }),
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export { autopilotAgent } from "./autopilot";
|
|
46
|
+
export { documenterAgent } from "./documenter";
|
|
47
|
+
export { metaprompterAgent } from "./metaprompter";
|
|
48
|
+
export { prReviewerAgent } from "./pr-reviewer";
|
|
49
|
+
export { researcherAgent } from "./researcher";
|