@plainconceptsplatform/agent-harness 2.2.1 → 2.4.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/README.md +23 -12
- package/{src → cli}/commands/join.js +3 -4
- package/{src → cli}/commands/migrate.js +1 -1
- package/{src → cli}/commands/update.js +13 -1
- package/{src → cli}/commands/wizard.js +1 -1
- package/{src → cli}/index.js +1 -1
- package/{src → cli}/presets/agents-content.json +4 -4
- package/cli/presets/browser.json +10 -0
- package/{src → cli}/presets/clean.json +21 -21
- package/{src → cli}/presets/optimization.json +37 -37
- package/{src → cli}/presets/platforms.json +76 -76
- package/{src → cli}/presets/quota.json +16 -16
- package/{src → cli}/presets/source.json +23 -23
- package/cli/steps/browser/index.js +48 -0
- package/{src → cli}/steps/clean/index.js +120 -120
- package/{src → cli}/steps/copy/agents.js +119 -119
- package/{src → cli}/steps/copy/commands.js +95 -95
- package/{src → cli}/steps/copy/fullstack-engineer.js +5 -1
- package/{src → cli}/steps/copy/index.js +1 -1
- package/{src → cli}/steps/copy/opencode-json.js +50 -1
- package/{src → cli}/steps/copy/skills.js +2 -2
- package/{src → cli}/steps/metadata/index.js +4 -0
- package/{src → cli}/steps/models/format.js +88 -88
- package/{src → cli}/steps/models/index.js +64 -64
- package/{src → cli}/steps/openspec/index.js +136 -136
- package/{src → cli}/steps/optimization/codegraph.js +127 -127
- package/cli/steps/optimization/detect.js +66 -0
- package/{src → cli}/steps/optimization/humanizer.js +17 -17
- package/{src → cli}/steps/optimization/index.js +163 -163
- package/{src → cli}/steps/optimization/memory.js +88 -88
- package/{src → cli}/steps/optimization/patch-guardrails.js +109 -109
- package/{src → cli}/steps/optimization/quota.js +119 -119
- package/{src → cli}/steps/optimization/simple-english.js +17 -17
- package/{src → cli}/steps/optimization/skills-lock.js +30 -30
- package/{src → cli}/steps/platform/index.js +109 -109
- package/{src → cli}/steps/source/index.js +123 -123
- package/cli/utils/agent-color.js +111 -0
- package/{src → cli}/utils/exec-spinner.js +47 -47
- package/{src → cli}/utils/exec.js +134 -134
- package/{src → cli}/utils/models-pricing.js +42 -42
- package/{src → cli}/utils/paths.js +1 -1
- package/{src → cli}/utils/process.js +3 -3
- package/{src → cli}/utils/terminal.js +6 -6
- package/harness/.agents/skills/browser-automation/SKILL.md +72 -0
- package/{src/content → harness}/.agents/skills/pc-make-engineer/SKILL.md +1 -1
- package/{src/content → harness}/.agents/skills/pc-make-engineer/template.md +1 -2
- package/{src/content → harness}/.agents/skills/pc-plan-archive/SKILL.md +3 -0
- package/{src/content → harness}/.agents/skills/pc-plan-explore/SKILL.md +3 -0
- package/{src/content → harness}/.agents/skills/pc-plan-goal/SKILL.md +5 -16
- package/{src/content → harness}/.agents/skills/pc-plan-goal/branching.md +1 -1
- package/{src/content → harness}/.agents/skills/pc-plan-goal/output.md +5 -8
- package/{src/content → harness}/.agents/skills/pc-plan-story/SKILL.md +3 -0
- package/{src/content → harness}/.agents/skills/pc-userstory-browser/SKILL.md +136 -132
- package/{src/content → harness}/.opencode/package.json +9 -10
- package/{src/content → harness}/.opencode/plugins/pc-subagent-tiers.js +91 -4
- package/{src/content → harness}/ARCHITECTURE.md +16 -16
- package/{src/content → harness}/DESIGN.md +16 -16
- package/{src/content → harness}/opencode.jsonc +11 -3
- package/{src/content → harness}/openspec/config.yaml +20 -20
- package/{src/content → harness}/skills-lock.json +17 -17
- package/package.json +7 -7
- package/src/content/.agents/skills/browser-automation/SKILL.md +0 -66
- package/src/presets/browser.json +0 -22
- package/src/steps/browser/index.js +0 -91
- /package/{src → cli}/commands/shared.js +0 -0
- /package/{src → cli}/commands/single.js +0 -0
- /package/{src → cli}/fragments/archive/az.md +0 -0
- /package/{src → cli}/fragments/archive/gh.md +0 -0
- /package/{src → cli}/fragments/archive/gl.md +0 -0
- /package/{src → cli}/fragments/archive/none.md +0 -0
- /package/{src → cli}/fragments/guardrails/codegraph.md +0 -0
- /package/{src → cli}/fragments/guardrails/humanizer.md +0 -0
- /package/{src → cli}/fragments/guardrails/memory.md +0 -0
- /package/{src → cli}/fragments/guardrails/rtk.md +0 -0
- /package/{src → cli}/fragments/guardrails/simple-english.md +0 -0
- /package/{src → cli}/fragments/ops-backlog/az.md +0 -0
- /package/{src → cli}/fragments/ops-backlog/gh.md +0 -0
- /package/{src → cli}/fragments/ops-backlog/jira.md +0 -0
- /package/{src → cli}/fragments/ops-evidence/az.md +0 -0
- /package/{src → cli}/fragments/ops-evidence/gh.md +0 -0
- /package/{src → cli}/fragments/ops-evidence/jira.md +0 -0
- /package/{src → cli}/fragments/ops-review/az.md +0 -0
- /package/{src → cli}/fragments/ops-review/gh.md +0 -0
- /package/{src → cli}/fragments/ops-review/gl.md +0 -0
- /package/{src → cli}/fragments/ops-ship/az.md +0 -0
- /package/{src → cli}/fragments/ops-ship/gh.md +0 -0
- /package/{src → cli}/fragments/ops-ship/gl.md +0 -0
- /package/{src → cli}/presets/models.json +0 -0
- /package/{src → cli}/presets/openspec.json +0 -0
- /package/{src → cli}/steps/models/write.js +0 -0
- /package/{src → cli}/utils/copy.js +0 -0
- /package/{src → cli}/utils/legacy-check.js +0 -0
- /package/{src → cli}/utils/models-cache.js +0 -0
- /package/{src → cli}/utils/update-manifest.js +0 -0
- /package/{src/content → harness}/.agents/skills/pc-guardrails-generic/SKILL.md +0 -0
- /package/{src/content → harness}/.agents/skills/pc-guardrails-project/SKILL.md +0 -0
- /package/{src/content → harness}/.agents/skills/pc-make-architecture/SKILL.md +0 -0
- /package/{src/content → harness}/.agents/skills/pc-make-architecture/structure-template.md +0 -0
- /package/{src/content → harness}/.agents/skills/pc-make-design/SKILL.md +0 -0
- /package/{src/content → harness}/.agents/skills/pc-make-engineer/signal-mapping.md +0 -0
- /package/{src/content → harness}/.agents/skills/pc-make-evidence-scaffold/SKILL.md +0 -0
- /package/{src/content → harness}/.agents/skills/pc-make-evidence-scaffold/evidence-contract.md +0 -0
- /package/{src/content → harness}/.agents/skills/pc-make-guardrails/SKILL.md +0 -0
- /package/{src/content → harness}/.agents/skills/pc-make-guardrails/category-reference.md +0 -0
- /package/{src/content → harness}/.agents/skills/pc-make-merge-risk-assess/SKILL.md +0 -0
- /package/{src/content → harness}/.agents/skills/pc-make-merge-risk-assess/category-reference.md +0 -0
- /package/{src/content → harness}/.agents/skills/pc-make-user-model/SKILL.md +0 -0
- /package/{src/content → harness}/.agents/skills/pc-ops-evidence/SKILL.md +0 -0
- /package/{src/content → harness}/.agents/skills/pc-ops-ship/SKILL.md +0 -0
- /package/{src/content → harness}/.agents/skills/pc-plan-apply/SKILL.md +0 -0
- /package/{src/content → harness}/.agents/skills/pc-plan-apply/simple-mode.md +0 -0
- /package/{src/content → harness}/.agents/skills/pc-plan-goal/failure-policy.md +0 -0
- /package/{src/content → harness}/.agents/skills/pc-plan-goal/output-mode.md +0 -0
- /package/{src/content → harness}/.agents/skills/pc-plan-propose/SKILL.md +0 -0
- /package/{src/content → harness}/.agents/skills/pc-plan-propose/task-annotation.md +0 -0
- /package/{src/content → harness}/.agents/skills/pc-plan-quick/SKILL.md +0 -0
- /package/{src/content → harness}/.agents/skills/pc-repo-audit/SKILL.md +0 -0
- /package/{src/content → harness}/.agents/skills/pc-repo-help/SKILL.md +0 -0
- /package/{src/content → harness}/.agents/skills/pc-repo-initialize/SKILL.md +0 -0
- /package/{src/content → harness}/.agents/skills/pc-repo-onboard/SKILL.md +0 -0
- /package/{src/content → harness}/.agents/skills/pc-repo-verify/SKILL.md +0 -0
- /package/{src/content → harness}/.agents/skills/pc-userstory-az/SKILL.md +0 -0
- /package/{src/content → harness}/.agents/skills/pc-userstory-gh/SKILL.md +0 -0
- /package/{src/content → harness}/.agents/skills/pc-userstory-jira/SKILL.md +0 -0
- /package/{src/content → harness}/.opencode/_gitignore +0 -0
- /package/{src/content → harness}/.opencode/commands/init.md +0 -0
- /package/{src/content → harness}/.opencode/commands/make-architecture.md +0 -0
- /package/{src/content → harness}/.opencode/commands/make-design.md +0 -0
- /package/{src/content → harness}/.opencode/commands/make-engineer.md +0 -0
- /package/{src/content → harness}/.opencode/commands/make-evidence-scaffold.md +0 -0
- /package/{src/content → harness}/.opencode/commands/make-guardrails.md +0 -0
- /package/{src/content → harness}/.opencode/commands/make-user-model.md +0 -0
- /package/{src/content → harness}/.opencode/commands/ops-backlog.md +0 -0
- /package/{src/content → harness}/.opencode/commands/ops-evidence.md +0 -0
- /package/{src/content → harness}/.opencode/commands/ops-review.md +0 -0
- /package/{src/content → harness}/.opencode/commands/ops-ship.md +0 -0
- /package/{src/content → harness}/.opencode/commands/plan-apply.md +0 -0
- /package/{src/content → harness}/.opencode/commands/plan-archive.md +0 -0
- /package/{src/content → harness}/.opencode/commands/plan-explore.md +0 -0
- /package/{src/content → harness}/.opencode/commands/plan-goal.md +0 -0
- /package/{src/content → harness}/.opencode/commands/plan-propose.md +0 -0
- /package/{src/content → harness}/.opencode/commands/plan-quick.md +0 -0
- /package/{src/content → harness}/.opencode/commands/plan-story.md +0 -0
- /package/{src/content → harness}/.opencode/commands/repo-audit.md +0 -0
- /package/{src/content → harness}/.opencode/commands/repo-help.md +0 -0
- /package/{src/content → harness}/.opencode/commands/repo-initialize.md +0 -0
- /package/{src/content → harness}/.opencode/commands/repo-onboard.md +0 -0
- /package/{src/content → harness}/.opencode/commands/repo-verify.md +0 -0
- /package/{src/content → harness}/.opencode/plugins/pc-subagent-monitor.js +0 -0
- /package/{src/content → harness}/.opencode/plugins/pc-system-reminders.js +0 -0
- /package/{src/content → harness}/.opencode/tui/pc-subagents.tsx +0 -0
- /package/{src/content → harness}/.opencode/tui.json +0 -0
- /package/{src/content → harness}/AGENTS.md +0 -0
- /package/{src/content → harness}/openspec/changes/archive/.gitkeep +0 -0
- /package/{src/content → harness}/openspec/specs/.gitkeep +0 -0
|
@@ -1,132 +1,136 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: pc-userstory
|
|
3
|
-
description: Parse work item from any URL using browser automation. Use when user provides a URL that doesn't match GitHub/Azure/Jira CLI platforms, or when backlog platform is 'browser'.
|
|
4
|
-
license: MIT
|
|
5
|
-
compatibility: Requires
|
|
6
|
-
metadata:
|
|
7
|
-
author: copilots
|
|
8
|
-
version: "
|
|
9
|
-
---
|
|
10
|
-
|
|
11
|
-
This skill is used when the backlog platform is set to "Others (Browser)": when there is no CLI integration for the backlog system, or the user doesn't have API tokens. Work items are read directly from the web page using
|
|
12
|
-
|
|
13
|
-
This skill overrides the `browser-automation` skill's external navigation restriction, but only for URLs the user explicitly provides as work items. Navigate only to URLs the user gives you.
|
|
14
|
-
|
|
15
|
-
## Prerequisites
|
|
16
|
-
|
|
17
|
-
-
|
|
18
|
-
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
-
|
|
53
|
-
-
|
|
54
|
-
-
|
|
55
|
-
-
|
|
56
|
-
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
-
|
|
104
|
-
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
-
|
|
110
|
-
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
-
|
|
116
|
-
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
-
|
|
122
|
-
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
-
|
|
132
|
-
-
|
|
1
|
+
---
|
|
2
|
+
name: pc-userstory
|
|
3
|
+
description: Parse work item from any URL using browser automation. Use when user provides a URL that doesn't match GitHub/Azure/Jira CLI platforms, or when backlog platform is 'browser'.
|
|
4
|
+
license: MIT
|
|
5
|
+
compatibility: Requires agent-browser CLI installed and openspec CLI.
|
|
6
|
+
metadata:
|
|
7
|
+
author: copilots
|
|
8
|
+
version: "2.0"
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
This skill is used when the backlog platform is set to "Others (Browser)": when there is no CLI integration for the backlog system, or the user doesn't have API tokens. Work items are read directly from the web page using agent-browser.
|
|
12
|
+
|
|
13
|
+
This skill overrides the `browser-automation` skill's external navigation restriction, but only for URLs the user explicitly provides as work items. Navigate only to URLs the user gives you.
|
|
14
|
+
|
|
15
|
+
## Prerequisites
|
|
16
|
+
|
|
17
|
+
- agent-browser installed (installed during onboarding) — verify with `agent-browser doctor`
|
|
18
|
+
- An authenticated session for the backlog system:
|
|
19
|
+
- agent-browser runs its own Chrome, not the user's daily browser. Login state persists per session via `--session <slug> --restore`: log in once, and later runs restore cookies automatically.
|
|
20
|
+
- On first use, the user logs in manually in the opened window; state is saved on close and auto-restored afterwards.
|
|
21
|
+
|
|
22
|
+
## Steps
|
|
23
|
+
|
|
24
|
+
1. **Extract the URL** from the user's message
|
|
25
|
+
- The user provides a direct URL to a work item, issue, ticket, or PBI
|
|
26
|
+
- Examples: `https://dev.azure.com/org/project/_workitems/edit/123`, `https://linear.app/team/issue/ENG-123`, `https://trello.com/c/abc123`, `https://your-tool.com/ticket/456`
|
|
27
|
+
|
|
28
|
+
2. **Open the URL in a persistent session**
|
|
29
|
+
```bash
|
|
30
|
+
agent-browser --session backlog --restore open "https://the-url-the-user-provided"
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
3. **Wait for the page to load**
|
|
34
|
+
```bash
|
|
35
|
+
agent-browser wait --load networkidle
|
|
36
|
+
```
|
|
37
|
+
Prefer load-state waits over fixed sleeps; for SPAs that render after idle, add `agent-browser wait --text "<known heading>"` when a stable string is known.
|
|
38
|
+
|
|
39
|
+
4. **Read the work item content**
|
|
40
|
+
```bash
|
|
41
|
+
agent-browser snapshot
|
|
42
|
+
```
|
|
43
|
+
The accessibility tree with `@ref` handles usually reveals the work item title, description, and fields more precisely than raw page text. Also useful:
|
|
44
|
+
```bash
|
|
45
|
+
agent-browser read # agent-readable text of the active tab
|
|
46
|
+
agent-browser get text "h1" # the heading, when present
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
5. **Parse work item fields**
|
|
50
|
+
|
|
51
|
+
From the snapshot and/or text, extract:
|
|
52
|
+
- Title/Summary: usually the main heading or the `<h1>` / page title
|
|
53
|
+
- Description: the body text, acceptance criteria, or "Definition of Done" section
|
|
54
|
+
- ID/Key: the work item ID from the URL or page (e.g. `123`, `ENG-123`)
|
|
55
|
+
- Status: if visible (e.g. "To Do", "In Progress", "Active")
|
|
56
|
+
- Assignee: if visible
|
|
57
|
+
- Priority: if visible
|
|
58
|
+
- Labels/Tags: if visible
|
|
59
|
+
|
|
60
|
+
If the page is a SPA that loads content dynamically:
|
|
61
|
+
- Wait for load state again (`agent-browser wait --load networkidle`)
|
|
62
|
+
- Take a fresh `snapshot` after the wait
|
|
63
|
+
- `agent-browser get url` confirms you are still on the work item
|
|
64
|
+
|
|
65
|
+
If a login page appears instead, the session is not authenticated: tell the user to log in manually in the opened browser window, then retry from step 2 with the same `--session backlog --restore` (the login is saved for future runs).
|
|
66
|
+
|
|
67
|
+
6. **Create OpenSpec Change**
|
|
68
|
+
```bash
|
|
69
|
+
openspec new change "{slug-from-title}"
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Write `proposal.md` with:
|
|
73
|
+
- Title: the work item title from the page
|
|
74
|
+
- Context: mention the source URL and the work item ID
|
|
75
|
+
- Requirements: extracted from description and acceptance criteria
|
|
76
|
+
- Scope: what's in/out based on the ticket
|
|
77
|
+
|
|
78
|
+
7. **Hand off to proposal.** Load the `pc-plan-propose` skill (interactive mode) to generate the proposal, specs, and tasks. After it completes, call the `question` tool:
|
|
79
|
+
|
|
80
|
+
```json
|
|
81
|
+
{
|
|
82
|
+
"questions": [
|
|
83
|
+
{
|
|
84
|
+
"header": "Ready to implement",
|
|
85
|
+
"question": "Ready to implement?",
|
|
86
|
+
"options": [
|
|
87
|
+
{ "label": "yes", "description": "Load the pc-plan-apply skill to start implementation." },
|
|
88
|
+
{ "label": "no", "description": "Stop here. You can run /plan-apply later." }
|
|
89
|
+
]
|
|
90
|
+
}
|
|
91
|
+
]
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Wait for confirmation before loading `pc-plan-apply`.
|
|
96
|
+
|
|
97
|
+
## Working with common backlog tools
|
|
98
|
+
|
|
99
|
+
### Azure DevOps (browser fallback)
|
|
100
|
+
- URL: `https://dev.azure.com/{org}/{project}/_workitems/edit/{id}`
|
|
101
|
+
- Title: visible in the work item header
|
|
102
|
+
- Description: "Description" field section
|
|
103
|
+
- Acceptance Criteria: "Acceptance Criteria" field section
|
|
104
|
+
- State: visible in the top-right area
|
|
105
|
+
|
|
106
|
+
### Linear
|
|
107
|
+
- URL: `https://linear.app/{team}/issue/{key}`
|
|
108
|
+
- Title: the issue title
|
|
109
|
+
- Description: the issue body
|
|
110
|
+
- Status: visible as a dropdown
|
|
111
|
+
|
|
112
|
+
### Jira (browser fallback)
|
|
113
|
+
- URL: `https://yoursite.atlassian.net/browse/{key}`
|
|
114
|
+
- Title: the issue summary
|
|
115
|
+
- Description: the description field
|
|
116
|
+
- Status: visible in the status badge
|
|
117
|
+
|
|
118
|
+
### Trello
|
|
119
|
+
- URL: `https://trello.com/c/{short-id}`
|
|
120
|
+
- Title: the card title
|
|
121
|
+
- Description: the card description
|
|
122
|
+
- Labels: visible as colored badges
|
|
123
|
+
|
|
124
|
+
### Other tools (generic)
|
|
125
|
+
- Look for `<h1>` or page title for the work item title
|
|
126
|
+
- Look for the main content area for description
|
|
127
|
+
- Use `agent-browser snapshot` to get structured accessibility tree data
|
|
128
|
+
|
|
129
|
+
## Rules
|
|
130
|
+
|
|
131
|
+
- Navigate only to URLs the user explicitly provide. Never guess or browse randomly.
|
|
132
|
+
- Reuse the `backlog` session (`--session backlog --restore`) so login state persists across runs.
|
|
133
|
+
- If the page requires login and the session is not authenticated, tell them to log in via the opened browser window and retry.
|
|
134
|
+
- For GitHub/Azure/Jira URLs when the CLI is configured for those platforms, use the CLI-based skill instead (faster, more reliable, no browser needed).
|
|
135
|
+
- This skill is read-only: no clicking buttons, no changing status.
|
|
136
|
+
- Browser is a backlog-only platform: it has no PR or repo integration. PR creation uses the repo platform configured separately.
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
{
|
|
2
|
-
"dependencies": {
|
|
3
|
-
"@opencode-ai/plugin": "1.18.19",
|
|
4
|
-
"@
|
|
5
|
-
"@
|
|
6
|
-
"@opentui/
|
|
7
|
-
"
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"dependencies": {
|
|
3
|
+
"@opencode-ai/plugin": "1.18.19",
|
|
4
|
+
"@mohak34/opencode-notifier": "0.2.8",
|
|
5
|
+
"@opentui/core": "0.5.6",
|
|
6
|
+
"@opentui/solid": "0.5.6",
|
|
7
|
+
"solid-js": "1.9.12"
|
|
8
|
+
}
|
|
9
|
+
}
|
|
@@ -24,19 +24,94 @@ const TIERS = ["build", "fast", "plan"]
|
|
|
24
24
|
// The two primaries, and the tier each takes its model from. plan denies edit
|
|
25
25
|
// so a planning session cannot mutate the tree; bash stays allowed because the
|
|
26
26
|
// planning skills shell out to git and openspec to read state.
|
|
27
|
+
//
|
|
28
|
+
// Their colours are theme keywords rather than derived hexes, and they are
|
|
29
|
+
// fixed: these are the two agents a human picks, so they should look the same
|
|
30
|
+
// in every project regardless of the theme in use.
|
|
27
31
|
const PRIMARIES = {
|
|
28
32
|
build: {
|
|
29
33
|
tier: "build",
|
|
34
|
+
color: "primary",
|
|
30
35
|
description: "Implement changes in this repository. Full write access, spawns specialist engineers for parallel work.",
|
|
31
36
|
permission: null,
|
|
32
37
|
},
|
|
33
38
|
plan: {
|
|
34
39
|
tier: "plan",
|
|
40
|
+
color: "warning",
|
|
35
41
|
description: "Explore and plan without touching the tree. Read-only: proposes work for build to carry out.",
|
|
36
42
|
permission: { edit: "deny" },
|
|
37
43
|
},
|
|
38
44
|
}
|
|
39
45
|
|
|
46
|
+
// opencode's theme keywords. Treated as unset so a name-derived hex wins: the
|
|
47
|
+
// old /make-engineer template asked whoever ran it to pick one of these and
|
|
48
|
+
// avoid collisions by hand, which does not survive more than a few agents.
|
|
49
|
+
const THEME_COLORS = new Set(["primary", "secondary", "accent", "success", "warning", "error", "info"])
|
|
50
|
+
|
|
51
|
+
// Mirrors cli/utils/agent-color.js in the CLI, duplicated because a plugin has
|
|
52
|
+
// to stand alone in the consumer repo. agent-color.test.js asserts the two stay
|
|
53
|
+
// in step; change one and change the other.
|
|
54
|
+
//
|
|
55
|
+
// Only the hue is hashed. Fixed saturation and lightness are what keep every
|
|
56
|
+
// result usable: hashing those too would eventually produce a near-grey,
|
|
57
|
+
// near-black or near-white agent, invisible against one theme or the other.
|
|
58
|
+
function agentColor(name) {
|
|
59
|
+
let h = 0x811c9dc5
|
|
60
|
+
for (let i = 0; i < name.length; i++) {
|
|
61
|
+
h ^= name.charCodeAt(i)
|
|
62
|
+
h = Math.imul(h, 0x01000193) >>> 0
|
|
63
|
+
}
|
|
64
|
+
const hue = (h >>> 0) % 360
|
|
65
|
+
const sat = 0.68
|
|
66
|
+
const light = 0.52
|
|
67
|
+
const c = (1 - Math.abs(2 * light - 1)) * sat
|
|
68
|
+
const x = c * (1 - Math.abs(((hue / 60) % 2) - 1))
|
|
69
|
+
const m = light - c / 2
|
|
70
|
+
const [r, g, b] =
|
|
71
|
+
hue < 60 ? [c, x, 0] :
|
|
72
|
+
hue < 120 ? [x, c, 0] :
|
|
73
|
+
hue < 180 ? [0, c, x] :
|
|
74
|
+
hue < 240 ? [0, x, c] :
|
|
75
|
+
hue < 300 ? [x, 0, c] :
|
|
76
|
+
[c, 0, x]
|
|
77
|
+
const toHex = v => Math.round((v + m) * 255).toString(16).padStart(2, "0")
|
|
78
|
+
return `#${toHex(r)}${toHex(g)}${toHex(b)}`.toUpperCase()
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/** A theme keyword or a missing value yields to the derived hex; a hex stays. */
|
|
82
|
+
function shouldDeriveColor(current) {
|
|
83
|
+
if (!current) return true
|
|
84
|
+
return THEME_COLORS.has(current.trim().toLowerCase())
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Render a colour for YAML frontmatter.
|
|
89
|
+
*
|
|
90
|
+
* A hex has to be quoted. `#` opens a comment in YAML, so `color: #D83155`
|
|
91
|
+
* parses as null and opencode refuses the agent with "Invalid input color".
|
|
92
|
+
* Theme keywords need no quoting and stay bare.
|
|
93
|
+
*/
|
|
94
|
+
function yamlColor(value) {
|
|
95
|
+
return value.startsWith("#") ? `"${value}"` : value
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function unquoteColor(raw) {
|
|
99
|
+
return (raw ?? "").trim().replace(/^["']/, "").replace(/["']$/, "")
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* The colour line an agent should have, or null when the current one is already
|
|
104
|
+
* right. Handles both choosing the colour and quoting it, so a file written by
|
|
105
|
+
* an earlier version with a bare hex is repaired in place rather than left
|
|
106
|
+
* broken.
|
|
107
|
+
*/
|
|
108
|
+
function colorLineFor(name, rawCurrent) {
|
|
109
|
+
const current = unquoteColor(rawCurrent)
|
|
110
|
+
const target = shouldDeriveColor(current) ? agentColor(name) : current
|
|
111
|
+
const rendered = yamlColor(target)
|
|
112
|
+
return (rawCurrent ?? "").trim() === rendered ? null : `color: ${rendered}`
|
|
113
|
+
}
|
|
114
|
+
|
|
40
115
|
const FULLSTACK_NAME = "fullstack-engineer"
|
|
41
116
|
const FULLSTACK_TEMPLATE = `${FULLSTACK_NAME}.md`
|
|
42
117
|
|
|
@@ -102,7 +177,7 @@ export const PcSubagentTiers = async ({ directory }) => {
|
|
|
102
177
|
// startup and are injected into generated files only, so a stale model: (from
|
|
103
178
|
// a prior `stampAgentModels` run, or from when these were primary) is
|
|
104
179
|
// stripped and the agent falls back to the session model in opencode.jsonc.
|
|
105
|
-
function normalizeTemplate(templateContent) {
|
|
180
|
+
function normalizeTemplate(templateContent, name) {
|
|
106
181
|
const fmMatch = templateContent.match(/^---\r?\n([\s\S]*?)\r?\n---/)
|
|
107
182
|
if (!fmMatch) return templateContent
|
|
108
183
|
|
|
@@ -113,6 +188,17 @@ export const PcSubagentTiers = async ({ directory }) => {
|
|
|
113
188
|
fm = /^mode:/m.test(fm) ? fm.replace(/^mode:.*$/m, 'mode: subagent') : `mode: subagent\n${fm}`
|
|
114
189
|
changed = true
|
|
115
190
|
}
|
|
191
|
+
// Give every agent a colour derived from its name, so the same engineer
|
|
192
|
+
// reads the same in any project and two agents never collide by accident.
|
|
193
|
+
// colorLineFor also repairs a bare #hex written by an earlier version,
|
|
194
|
+
// which YAML read as a comment and opencode rejected outright.
|
|
195
|
+
if (name) {
|
|
196
|
+
const colorLine = colorLineFor(name, fm.match(/^color:\s*(.+)$/m)?.[1])
|
|
197
|
+
if (colorLine) {
|
|
198
|
+
fm = /^color:/m.test(fm) ? fm.replace(/^color:.*$/m, () => colorLine) : `${fm}\n${colorLine}`
|
|
199
|
+
changed = true
|
|
200
|
+
}
|
|
201
|
+
}
|
|
116
202
|
if (/^model:/m.test(fm)) {
|
|
117
203
|
// Remove the model: line and its trailing newline without leaving a
|
|
118
204
|
// leading blank line (model: can be the first frontmatter entry).
|
|
@@ -140,7 +226,7 @@ export const PcSubagentTiers = async ({ directory }) => {
|
|
|
140
226
|
'mode: primary',
|
|
141
227
|
]
|
|
142
228
|
if (model) lines.push(`model: ${model}`)
|
|
143
|
-
lines.push(
|
|
229
|
+
lines.push(`color: ${yamlColor(spec.color)}`)
|
|
144
230
|
lines.push('permission:')
|
|
145
231
|
// plan denies edit; everything else stays allowed so the planning skills can
|
|
146
232
|
// still read the tree, shell out to git and openspec, and spawn engineers.
|
|
@@ -179,7 +265,7 @@ export const PcSubagentTiers = async ({ directory }) => {
|
|
|
179
265
|
if (hasFullstack) {
|
|
180
266
|
const fullstackPath = path.join(agentsDir, FULLSTACK_TEMPLATE)
|
|
181
267
|
const rawFullstack = await fs.readFile(fullstackPath, "utf-8")
|
|
182
|
-
const fullstack = normalizeTemplate(rawFullstack)
|
|
268
|
+
const fullstack = normalizeTemplate(rawFullstack, FULLSTACK_NAME)
|
|
183
269
|
if (fullstack !== rawFullstack) {
|
|
184
270
|
await writeIfChanged(fullstackPath, fullstack)
|
|
185
271
|
console.error(`[pc-subagent-tiers] Normalized ${FULLSTACK_TEMPLATE} (mode: subagent)`)
|
|
@@ -198,6 +284,7 @@ export const PcSubagentTiers = async ({ directory }) => {
|
|
|
198
284
|
...cfg.agent[name],
|
|
199
285
|
mode: 'primary',
|
|
200
286
|
description: spec.description,
|
|
287
|
+
color: spec.color,
|
|
201
288
|
...(model ? { model } : {}),
|
|
202
289
|
...(spec.permission ? { permission: { ...cfg.agent[name]?.permission, ...spec.permission } } : {}),
|
|
203
290
|
}
|
|
@@ -211,7 +298,7 @@ export const PcSubagentTiers = async ({ directory }) => {
|
|
|
211
298
|
const templateContents = await Promise.all(
|
|
212
299
|
templates.map(async name => {
|
|
213
300
|
const rawContent = await fs.readFile(path.join(agentsDir, `${name}.md`), "utf-8")
|
|
214
|
-
const content = normalizeTemplate(rawContent)
|
|
301
|
+
const content = normalizeTemplate(rawContent, name)
|
|
215
302
|
// If the template had the wrong mode or a stale model:, persist the fix to disk
|
|
216
303
|
if (content !== rawContent) {
|
|
217
304
|
await writeIfChanged(path.join(agentsDir, `${name}.md`), content)
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
> NOT GENERATED YET
|
|
2
|
-
>
|
|
3
|
-
> This file has not been populated yet. It is intentionally empty.
|
|
4
|
-
>
|
|
5
|
-
> **If this is a greenfield project** (no codebase exists yet): skip this for now.
|
|
6
|
-
> Come back and run `/make-architecture` once you have meaningful code, structure, or infrastructure in place.
|
|
7
|
-
>
|
|
8
|
-
> **If this is a brownfield project** (existing codebase): run this command now to generate the architecture documentation:
|
|
9
|
-
>
|
|
10
|
-
> ```
|
|
11
|
-
> /make-architecture
|
|
12
|
-
> ```
|
|
13
|
-
>
|
|
14
|
-
> This command analyzes your folder structure, config files, routes, data models, integrations, and build setup,
|
|
15
|
-
> then writes a complete ARCHITECTURE.md covering components, data flow, tech stack, deployment, and more.
|
|
16
|
-
> It is safe to rerun any time the architecture changes significantly.
|
|
1
|
+
> NOT GENERATED YET
|
|
2
|
+
>
|
|
3
|
+
> This file has not been populated yet. It is intentionally empty.
|
|
4
|
+
>
|
|
5
|
+
> **If this is a greenfield project** (no codebase exists yet): skip this for now.
|
|
6
|
+
> Come back and run `/make-architecture` once you have meaningful code, structure, or infrastructure in place.
|
|
7
|
+
>
|
|
8
|
+
> **If this is a brownfield project** (existing codebase): run this command now to generate the architecture documentation:
|
|
9
|
+
>
|
|
10
|
+
> ```
|
|
11
|
+
> /make-architecture
|
|
12
|
+
> ```
|
|
13
|
+
>
|
|
14
|
+
> This command analyzes your folder structure, config files, routes, data models, integrations, and build setup,
|
|
15
|
+
> then writes a complete ARCHITECTURE.md covering components, data flow, tech stack, deployment, and more.
|
|
16
|
+
> It is safe to rerun any time the architecture changes significantly.
|
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
> NOT GENERATED YET
|
|
2
|
-
>
|
|
3
|
-
> This file has not been populated yet. It is intentionally empty.
|
|
4
|
-
>
|
|
5
|
-
> **If this is a greenfield project** (no UI exists yet): skip this for now.
|
|
6
|
-
> Come back and run `/make-design` once you have a design system, UI components, or styles in place.
|
|
7
|
-
>
|
|
8
|
-
> **If this is a brownfield project** (existing UI/styles): run this command now to generate the design documentation:
|
|
9
|
-
>
|
|
10
|
-
> ```
|
|
11
|
-
> /make-design
|
|
12
|
-
> ```
|
|
13
|
-
>
|
|
14
|
-
> This command analyzes your CSS, Tailwind config, component files, and design tokens,
|
|
15
|
-
> then writes a complete DESIGN.md with structured YAML tokens and written design intent.
|
|
16
|
-
> It is safe to rerun any time your design system changes.
|
|
1
|
+
> NOT GENERATED YET
|
|
2
|
+
>
|
|
3
|
+
> This file has not been populated yet. It is intentionally empty.
|
|
4
|
+
>
|
|
5
|
+
> **If this is a greenfield project** (no UI exists yet): skip this for now.
|
|
6
|
+
> Come back and run `/make-design` once you have a design system, UI components, or styles in place.
|
|
7
|
+
>
|
|
8
|
+
> **If this is a brownfield project** (existing UI/styles): run this command now to generate the design documentation:
|
|
9
|
+
>
|
|
10
|
+
> ```
|
|
11
|
+
> /make-design
|
|
12
|
+
> ```
|
|
13
|
+
>
|
|
14
|
+
> This command analyzes your CSS, Tailwind config, component files, and design tokens,
|
|
15
|
+
> then writes a complete DESIGN.md with structured YAML tokens and written design intent.
|
|
16
|
+
> It is safe to rerun any time your design system changes.
|
|
@@ -4,9 +4,15 @@
|
|
|
4
4
|
"AGENTS.md"
|
|
5
5
|
],
|
|
6
6
|
"plugin": [
|
|
7
|
-
"@different-ai/opencode-browser@4.6.1",
|
|
8
7
|
"@mohak34/opencode-notifier@0.2.8"
|
|
9
8
|
],
|
|
9
|
+
"mcp": {
|
|
10
|
+
"agent-browser": {
|
|
11
|
+
"type": "local",
|
|
12
|
+
"command": ["agent-browser", "mcp", "--tools", "core"],
|
|
13
|
+
"enabled": true
|
|
14
|
+
}
|
|
15
|
+
},
|
|
10
16
|
"experimental": {
|
|
11
17
|
"mcp_timeout": 300000
|
|
12
18
|
},
|
|
@@ -23,12 +29,14 @@
|
|
|
23
29
|
"skills": {
|
|
24
30
|
"paths": [".agents/skills"]
|
|
25
31
|
},
|
|
26
|
-
// build and plan are the only primaries
|
|
32
|
+
// build and plan are the only primaries, and plan is the default: a session
|
|
33
|
+
// starts read-only and you switch to build once you know what to change.
|
|
34
|
+
// The pc-subagent-tiers plugin
|
|
27
35
|
// regenerates .opencode/agents/{build,plan}.md from fullstack-engineer.md on
|
|
28
36
|
// every startup and overrides these two entries with the resolved tier model,
|
|
29
37
|
// so what is here is only the floor if the plugin cannot run. Every engineer
|
|
30
38
|
// is mode: subagent and reached through task(), never picked by a human.
|
|
31
|
-
"default_agent": "
|
|
39
|
+
"default_agent": "plan",
|
|
32
40
|
"agent": {
|
|
33
41
|
"build": { "mode": "primary" },
|
|
34
42
|
"plan": {
|
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
schema: spec-driven
|
|
2
|
-
|
|
3
|
-
# Project context (optional)
|
|
4
|
-
# This is shown to AI when creating artifacts.
|
|
5
|
-
# Add your tech stack, conventions, style guides, domain knowledge, etc.
|
|
6
|
-
# Example:
|
|
7
|
-
# context: |
|
|
8
|
-
# Tech stack: TypeScript, React, Node.js
|
|
9
|
-
# We use conventional commits
|
|
10
|
-
# Domain: e-commerce platform
|
|
11
|
-
|
|
12
|
-
# Per-artifact rules (optional)
|
|
13
|
-
# Add custom rules for specific artifacts.
|
|
14
|
-
# Example:
|
|
15
|
-
# rules:
|
|
16
|
-
# proposal:
|
|
17
|
-
# - Keep proposals under 500 words
|
|
18
|
-
# - Always include a "Non-goals" section
|
|
19
|
-
# tasks:
|
|
20
|
-
# - Break tasks into chunks of max 2 hours
|
|
1
|
+
schema: spec-driven
|
|
2
|
+
|
|
3
|
+
# Project context (optional)
|
|
4
|
+
# This is shown to AI when creating artifacts.
|
|
5
|
+
# Add your tech stack, conventions, style guides, domain knowledge, etc.
|
|
6
|
+
# Example:
|
|
7
|
+
# context: |
|
|
8
|
+
# Tech stack: TypeScript, React, Node.js
|
|
9
|
+
# We use conventional commits
|
|
10
|
+
# Domain: e-commerce platform
|
|
11
|
+
|
|
12
|
+
# Per-artifact rules (optional)
|
|
13
|
+
# Add custom rules for specific artifacts.
|
|
14
|
+
# Example:
|
|
15
|
+
# rules:
|
|
16
|
+
# proposal:
|
|
17
|
+
# - Keep proposals under 500 words
|
|
18
|
+
# - Always include a "Non-goals" section
|
|
19
|
+
# tasks:
|
|
20
|
+
# - Break tasks into chunks of max 2 hours
|
|
@@ -1,17 +1,17 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 1,
|
|
3
|
-
"skills": {
|
|
4
|
-
"find-skills": {
|
|
5
|
-
"source": "vercel-labs/skills",
|
|
6
|
-
"sourceType": "github",
|
|
7
|
-
"skillPath": "skills/find-skills/SKILL.md",
|
|
8
|
-
"computedHash": "781bd6d3f9b19f8c9af6b53d8d0e4876d0183841b565db34ca7092ffa412d111"
|
|
9
|
-
},
|
|
10
|
-
"user-story": {
|
|
11
|
-
"source": "deanpeters/product-manager-skills",
|
|
12
|
-
"sourceType": "github",
|
|
13
|
-
"skillPath": "skills/user-story/SKILL.md",
|
|
14
|
-
"computedHash": "user-story-placeholder"
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"version": 1,
|
|
3
|
+
"skills": {
|
|
4
|
+
"find-skills": {
|
|
5
|
+
"source": "vercel-labs/skills",
|
|
6
|
+
"sourceType": "github",
|
|
7
|
+
"skillPath": "skills/find-skills/SKILL.md",
|
|
8
|
+
"computedHash": "781bd6d3f9b19f8c9af6b53d8d0e4876d0183841b565db34ca7092ffa412d111"
|
|
9
|
+
},
|
|
10
|
+
"user-story": {
|
|
11
|
+
"source": "deanpeters/product-manager-skills",
|
|
12
|
+
"sourceType": "github",
|
|
13
|
+
"skillPath": "skills/user-story/SKILL.md",
|
|
14
|
+
"computedHash": "user-story-placeholder"
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|