@plainconceptsplatform/agent-harness 2.0.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 +419 -0
- package/package.json +68 -0
- package/src/commands/join.js +244 -0
- package/src/commands/shared.js +27 -0
- package/src/commands/single.js +79 -0
- package/src/commands/update.js +109 -0
- package/src/commands/wizard.js +134 -0
- package/src/content/.agents/skills/browser-automation/SKILL.md +66 -0
- package/src/content/.agents/skills/pc-guardrails-generic/SKILL.md +68 -0
- package/src/content/.agents/skills/pc-guardrails-project/SKILL.md +8 -0
- package/src/content/.agents/skills/pc-make-architecture/SKILL.md +51 -0
- package/src/content/.agents/skills/pc-make-architecture/structure-template.md +38 -0
- package/src/content/.agents/skills/pc-make-design/SKILL.md +68 -0
- package/src/content/.agents/skills/pc-make-engineer/SKILL.md +219 -0
- package/src/content/.agents/skills/pc-make-engineer/signal-mapping.md +68 -0
- package/src/content/.agents/skills/pc-make-engineer/template.md +81 -0
- package/src/content/.agents/skills/pc-make-evidence-scaffold/SKILL.md +18 -0
- package/src/content/.agents/skills/pc-make-evidence-scaffold/evidence-contract.md +29 -0
- package/src/content/.agents/skills/pc-make-guardrails/SKILL.md +74 -0
- package/src/content/.agents/skills/pc-make-guardrails/category-reference.md +68 -0
- package/src/content/.agents/skills/pc-make-merge-risk-assess/SKILL.md +70 -0
- package/src/content/.agents/skills/pc-make-merge-risk-assess/category-reference.md +98 -0
- package/src/content/.agents/skills/pc-make-user-model/SKILL.md +66 -0
- package/src/content/.agents/skills/pc-ops-evidence/SKILL.md +127 -0
- package/src/content/.agents/skills/pc-ops-ship/SKILL.md +18 -0
- package/src/content/.agents/skills/pc-plan-apply/SKILL.md +83 -0
- package/src/content/.agents/skills/pc-plan-apply/simple-mode.md +21 -0
- package/src/content/.agents/skills/pc-plan-archive/SKILL.md +63 -0
- package/src/content/.agents/skills/pc-plan-explore/SKILL.md +9 -0
- package/src/content/.agents/skills/pc-plan-goal/SKILL.md +94 -0
- package/src/content/.agents/skills/pc-plan-goal/branching.md +30 -0
- package/src/content/.agents/skills/pc-plan-goal/failure-policy.md +30 -0
- package/src/content/.agents/skills/pc-plan-goal/output-mode.md +9 -0
- package/src/content/.agents/skills/pc-plan-goal/output.md +68 -0
- package/src/content/.agents/skills/pc-plan-propose/SKILL.md +125 -0
- package/src/content/.agents/skills/pc-plan-propose/task-annotation.md +39 -0
- package/src/content/.agents/skills/pc-plan-quick/SKILL.md +62 -0
- package/src/content/.agents/skills/pc-plan-story/SKILL.md +146 -0
- package/src/content/.agents/skills/pc-repo-audit/SKILL.md +44 -0
- package/src/content/.agents/skills/pc-repo-help/SKILL.md +91 -0
- package/src/content/.agents/skills/pc-repo-initialize/SKILL.md +130 -0
- package/src/content/.agents/skills/pc-repo-onboard/SKILL.md +87 -0
- package/src/content/.agents/skills/pc-repo-verify/SKILL.md +34 -0
- package/src/content/.agents/skills/pc-userstory-az/SKILL.md +157 -0
- package/src/content/.agents/skills/pc-userstory-browser/SKILL.md +132 -0
- package/src/content/.agents/skills/pc-userstory-gh/SKILL.md +120 -0
- package/src/content/.agents/skills/pc-userstory-jira/SKILL.md +131 -0
- package/src/content/.opencode/_gitignore +7 -0
- package/src/content/.opencode/commands/init.md +5 -0
- package/src/content/.opencode/commands/make-architecture.md +5 -0
- package/src/content/.opencode/commands/make-design.md +5 -0
- package/src/content/.opencode/commands/make-engineer.md +5 -0
- package/src/content/.opencode/commands/make-evidence-scaffold.md +5 -0
- package/src/content/.opencode/commands/make-guardrails.md +5 -0
- package/src/content/.opencode/commands/make-user-model.md +5 -0
- package/src/content/.opencode/commands/ops-backlog.md +10 -0
- package/src/content/.opencode/commands/ops-evidence.md +9 -0
- package/src/content/.opencode/commands/ops-review.md +8 -0
- package/src/content/.opencode/commands/ops-ship.md +9 -0
- package/src/content/.opencode/commands/plan-apply.md +9 -0
- package/src/content/.opencode/commands/plan-archive.md +5 -0
- package/src/content/.opencode/commands/plan-explore.md +9 -0
- package/src/content/.opencode/commands/plan-goal.md +5 -0
- package/src/content/.opencode/commands/plan-propose.md +9 -0
- package/src/content/.opencode/commands/plan-quick.md +5 -0
- package/src/content/.opencode/commands/plan-story.md +9 -0
- package/src/content/.opencode/commands/repo-audit.md +5 -0
- package/src/content/.opencode/commands/repo-help.md +5 -0
- package/src/content/.opencode/commands/repo-initialize.md +5 -0
- package/src/content/.opencode/commands/repo-onboard.md +5 -0
- package/src/content/.opencode/commands/repo-verify.md +5 -0
- package/src/content/.opencode/package.json +10 -0
- package/src/content/.opencode/plugins/pc-subagent-monitor.js +139 -0
- package/src/content/.opencode/plugins/pc-subagent-tiers.js +179 -0
- package/src/content/.opencode/plugins/pc-system-reminders.js +96 -0
- package/src/content/.opencode/plugins/pc-system-reminders.test.js +35 -0
- package/src/content/.opencode/tui/pc-subagents.tsx +98 -0
- package/src/content/.opencode/tui.json +6 -0
- package/src/content/AGENTS.md +71 -0
- package/src/content/ARCHITECTURE.md +16 -0
- package/src/content/DESIGN.md +16 -0
- package/src/content/opencode.jsonc +31 -0
- package/src/content/openspec/changes/archive/.gitkeep +0 -0
- package/src/content/openspec/config.yaml +20 -0
- package/src/content/openspec/specs/.gitkeep +0 -0
- package/src/content/skills-lock.json +17 -0
- package/src/fragments/archive/az.md +95 -0
- package/src/fragments/archive/gh.md +94 -0
- package/src/fragments/archive/gl.md +94 -0
- package/src/fragments/archive/none.md +73 -0
- package/src/fragments/guardrails/codegraph.md +7 -0
- package/src/fragments/guardrails/humanizer.md +4 -0
- package/src/fragments/guardrails/memory.md +4 -0
- package/src/fragments/guardrails/rtk.md +3 -0
- package/src/fragments/guardrails/simple-english.md +4 -0
- package/src/fragments/ops-backlog/az.md +29 -0
- package/src/fragments/ops-backlog/gh.md +30 -0
- package/src/fragments/ops-backlog/jira.md +29 -0
- package/src/fragments/ops-evidence/az.md +41 -0
- package/src/fragments/ops-evidence/gh.md +53 -0
- package/src/fragments/ops-evidence/jira.md +38 -0
- package/src/fragments/ops-review/az.md +63 -0
- package/src/fragments/ops-review/gh.md +53 -0
- package/src/fragments/ops-review/gl.md +57 -0
- package/src/fragments/ops-ship/az.md +81 -0
- package/src/fragments/ops-ship/gh.md +69 -0
- package/src/fragments/ops-ship/gl.md +86 -0
- package/src/index.js +107 -0
- package/src/presets/agents-content.json +53 -0
- package/src/presets/browser.json +22 -0
- package/src/presets/clean.json +21 -0
- package/src/presets/models.json +68 -0
- package/src/presets/openspec.json +1 -0
- package/src/presets/optimization.json +37 -0
- package/src/presets/platforms.json +76 -0
- package/src/presets/quota.json +16 -0
- package/src/presets/source.json +23 -0
- package/src/steps/browser/index.js +91 -0
- package/src/steps/clean/index.js +120 -0
- package/src/steps/copy/agents.js +118 -0
- package/src/steps/copy/commands.js +91 -0
- package/src/steps/copy/fullstack-engineer.js +83 -0
- package/src/steps/copy/index.js +88 -0
- package/src/steps/copy/opencode-json.js +129 -0
- package/src/steps/copy/skills.js +196 -0
- package/src/steps/metadata/index.js +108 -0
- package/src/steps/models/format.js +88 -0
- package/src/steps/models/index.js +64 -0
- package/src/steps/models/write.js +34 -0
- package/src/steps/openspec/index.js +136 -0
- package/src/steps/optimization/codegraph.js +127 -0
- package/src/steps/optimization/humanizer.js +17 -0
- package/src/steps/optimization/index.js +163 -0
- package/src/steps/optimization/memory.js +88 -0
- package/src/steps/optimization/patch-guardrails.js +108 -0
- package/src/steps/optimization/quota.js +119 -0
- package/src/steps/optimization/simple-english.js +17 -0
- package/src/steps/optimization/skills-lock.js +30 -0
- package/src/steps/platform/index.js +109 -0
- package/src/steps/source/index.js +123 -0
- package/src/utils/copy.js +108 -0
- package/src/utils/exec-spinner.js +47 -0
- package/src/utils/exec.js +134 -0
- package/src/utils/legacy-check.js +30 -0
- package/src/utils/models-cache.js +58 -0
- package/src/utils/models-pricing.js +42 -0
- package/src/utils/paths.js +64 -0
- package/src/utils/process.js +3 -0
- package/src/utils/terminal.js +6 -0
- package/src/utils/update-manifest.js +49 -0
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
**Browser MCP tools are FORBIDDEN for all Azure DevOps operations. Use `az boards` CLI only. If `az` is unavailable, skip publishing (report it) — do not fail the pipeline unless the caller declared publishing a ship gate.**
|
|
2
|
+
|
|
3
|
+
Publish one status comment for every manifest. A `blocked` or `failed` manifest must include its status and reason, never a success claim.
|
|
4
|
+
|
|
5
|
+
### Step 1 — Image hosting caveat
|
|
6
|
+
|
|
7
|
+
Azure DevOps discussion comments do not render an image from a repo blob URL the way GitHub does, and `az boards` cannot upload an attachment inline. Use text evidence and derive a commit-pinned repository URL from `git remote get-url origin` when possible. Otherwise include the committed asset path, branch, and SHA.
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
Screenshot committed at: {asset-path} (branch {branch}, commit {sha})
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
### Step 2 — Build the comment with a stable marker (idempotent)
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
<!-- pc-visual-evidence:{change-id} -->
|
|
17
|
+
|
|
18
|
+
Status: `{status}`
|
|
19
|
+
|
|
20
|
+
{reason?}
|
|
21
|
+
|
|
22
|
+
Manifest and assets: {commit-pinned links when available, otherwise committed paths and SHA}
|
|
23
|
+
|
|
24
|
+
{prMarkdown}
|
|
25
|
+
|
|
26
|
+
{image-line?}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### Step 3 — Upsert the discussion comment on the work item (and the PR when provided)
|
|
30
|
+
|
|
31
|
+
`az boards work-item update --discussion` appends a comment; to stay idempotent, first read existing discussion comments and skip if one already carries the marker for this change id, otherwise post:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
# best-effort existing-comment check via the work-item comments API
|
|
35
|
+
az boards work-item show --id {work-item-id} --query 'fields."System.History"' -o tsv 2>/dev/null | grep -q "pc-visual-evidence:{change-id}" \
|
|
36
|
+
|| az boards work-item update --id {work-item-id} --discussion "$BODY"
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
When a PR number is provided, also add the same body as a PR thread comment (`az repos pr` thread APIs) if available.
|
|
40
|
+
|
|
41
|
+
- If a comment call fails: report it. Fail the run ONLY when publishing was declared a ship gate; otherwise continue.
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
**ALL GitHub data MUST come from `gh` CLI. NEVER use webfetch, HTTP requests, or browser MCP tools for GitHub. If `gh` is unavailable, skip publishing (report it) — do not fail the pipeline over it unless the caller declared publishing a ship gate.**
|
|
2
|
+
Always pass `--repo {owner}/{repo}` (or `repos/{owner}/{repo}` for `gh api`) explicitly.
|
|
3
|
+
|
|
4
|
+
Publish one status comment for every manifest. A `blocked` or `failed` manifest must include its status and reason, never a success claim.
|
|
5
|
+
|
|
6
|
+
### Step 1 — Build commit-pinned repository links
|
|
7
|
+
|
|
8
|
+
An embedded image must be a raw URL pinned to the commit that actually contains it, and that commit must be pushed. For each asset in `evidence.json`:
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
SHA="$(git log -n 1 --format=%H -- '{asset-path}')" # the commit that added this asset
|
|
12
|
+
[ -z "$SHA" ] && echo "asset not committed: {asset-path}" && exit-skip
|
|
13
|
+
gh api "repos/{owner}/{repo}/contents/{asset-path}?ref=$SHA" --silent # 404 → not pushed yet → skip embedding
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Build a blob link for every committed manifest and asset: `https://github.com/{owner}/{repo}/blob/{SHA}/{asset-path}`. Use the raw URL only for a verified embeddable image: `https://raw.githubusercontent.com/{owner}/{repo}/{SHA}/{asset-path}`. If verification fails, include the asset path and SHA as text; never post a dead link.
|
|
17
|
+
|
|
18
|
+
### Step 2 — Build the comment body with a stable marker (idempotent)
|
|
19
|
+
|
|
20
|
+
Prefix the body with a hidden marker so re-runs update the same comment instead of piling on:
|
|
21
|
+
|
|
22
|
+
```
|
|
23
|
+
<!-- pc-visual-evidence:{change-id} -->
|
|
24
|
+
|
|
25
|
+
Status: `{status}`
|
|
26
|
+
|
|
27
|
+
{reason?}
|
|
28
|
+
|
|
29
|
+
Manifest: {commit-pinned evidence.json link}
|
|
30
|
+
|
|
31
|
+
Assets: {commit-pinned asset links}
|
|
32
|
+
|
|
33
|
+
{prMarkdown}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### Step 3 — Upsert the comment on BOTH the issue and the PR
|
|
37
|
+
|
|
38
|
+
For each target number (the originating issue, and the PR number when provided), find an existing marked comment and PATCH it, else POST a new one:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
# find existing
|
|
42
|
+
ID="$(gh api "repos/{owner}/{repo}/issues/{number}/comments" --paginate --jq \
|
|
43
|
+
'.[] | select(.body | contains("<!-- pc-visual-evidence:{change-id} -->")) | .id' | head -1)"
|
|
44
|
+
|
|
45
|
+
if [ -n "$ID" ]; then
|
|
46
|
+
gh api --method PATCH "repos/{owner}/{repo}/issues/comments/$ID" -f body="$BODY" --silent
|
|
47
|
+
else
|
|
48
|
+
gh api --method POST "repos/{owner}/{repo}/issues/{number}/comments" -f body="$BODY" --silent
|
|
49
|
+
fi
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
- Text-only (no verified image, or `default` mode / nothing pushed): drop the image lines, keep the summary (tasks N/N, verification result, commits).
|
|
53
|
+
- If a comment call fails: report it. Fail the run ONLY when the caller declared publishing a ship gate; otherwise continue.
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
**NEVER use browser tools to navigate to atlassian.net: use `acli` CLI only. If `acli` is unavailable, skip publishing (report it) — do not fail the pipeline unless the caller declared publishing a ship gate.**
|
|
2
|
+
|
|
3
|
+
Publish one status comment for every manifest. A `blocked` or `failed` manifest must include its status and reason, never a success claim.
|
|
4
|
+
|
|
5
|
+
### Step 1 — Image hosting caveat
|
|
6
|
+
|
|
7
|
+
Jira comments cannot embed an image from a repo blob URL, and `acli` does not upload attachments inline. Use text evidence and derive a commit-pinned repository URL from `git remote get-url origin` when possible. Otherwise include the committed asset path, branch, and SHA:
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
Screenshot committed at: {asset-path} (branch {branch}, commit {sha})
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
### Step 2 — Build the comment with a stable marker (idempotent)
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
<!-- pc-visual-evidence:{change-id} -->
|
|
17
|
+
|
|
18
|
+
Status: `{status}`
|
|
19
|
+
|
|
20
|
+
{reason?}
|
|
21
|
+
|
|
22
|
+
Manifest and assets: {commit-pinned links when available, otherwise committed paths and SHA}
|
|
23
|
+
|
|
24
|
+
{prMarkdown}
|
|
25
|
+
|
|
26
|
+
{image-line?}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### Step 3 — Upsert the comment on the issue
|
|
30
|
+
|
|
31
|
+
Keep it idempotent: list existing comments and skip if one already carries the marker for this change id, otherwise add:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
acli jira issue comment list --key {issue-key} 2>/dev/null | grep -q "pc-visual-evidence:{change-id}" \
|
|
35
|
+
|| acli jira issue comment --key {issue-key} --body "$BODY"
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
- If the comment command fails: report it. Fail the run ONLY when publishing was declared a ship gate; otherwise continue.
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
**Browser MCP tools are FORBIDDEN for all Azure DevOps operations.**
|
|
2
|
+
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
### Step 1: Find PRs
|
|
6
|
+
|
|
7
|
+
If PR link provided, extract ID from URL. Otherwise:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
az repos pr list --repository {repo} --status active --top 1
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
### Step 2: Read comment threads
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
az devops invoke \
|
|
17
|
+
--area git --resource pullRequestThreads \
|
|
18
|
+
--route-parameters project={project} repositoryId={repo} pullRequestId={id} \
|
|
19
|
+
--http-method GET --api-version 7.1
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
### Step 3: Categorize feedback
|
|
23
|
+
|
|
24
|
+
| Category | Description | Action |
|
|
25
|
+
| ------------- | ----------------------------------- | ----------------------------------- |
|
|
26
|
+
| `code-change` | Reviewer requests code modification | Return to lead to spawn specialists |
|
|
27
|
+
| `spec-update` | Affects proposal, design, or tasks | Update openspec artifacts |
|
|
28
|
+
| `question` | Reviewer asks a question | Reply with answer |
|
|
29
|
+
| `resolved` | Thread already resolved | Skip |
|
|
30
|
+
|
|
31
|
+
### Step 4: Update openspec (if spec-update)
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
git branch --show-current
|
|
35
|
+
# feature/193208-roles-crud → change: us-193208-roles-crud
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Update: `openspec/changes/{change}/proposal.md`, `design.md`, or `tasks.md` as appropriate.
|
|
39
|
+
|
|
40
|
+
### Step 5: Reply to each thread
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
az devops invoke \
|
|
44
|
+
--area git --resource pullRequestThreadComments \
|
|
45
|
+
--route-parameters project={project} repositoryId={repo} pullRequestId={id} threadId={tid} \
|
|
46
|
+
--http-method POST --api-version 7.1 --in-file reply.json
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
`reply.json`:
|
|
50
|
+
|
|
51
|
+
```json
|
|
52
|
+
{
|
|
53
|
+
"comments": [
|
|
54
|
+
{
|
|
55
|
+
"parentCommentId": 1,
|
|
56
|
+
"content": "Acknowledged, applying this change now.",
|
|
57
|
+
"commentType": 1
|
|
58
|
+
}
|
|
59
|
+
]
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
---
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
**ALL GitHub data MUST come from `gh` CLI. NEVER use webfetch, HTTP requests, or browser MCP tools for GitHub operations, even if gh CLI fails. If `gh` is unavailable, report as a blocker.**
|
|
2
|
+
Always pass `--repo {owner}/{repo}` explicitly, never rely on git context to resolve the repo.
|
|
3
|
+
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
### Step 1: Find PRs
|
|
7
|
+
|
|
8
|
+
If PR link provided, extract number from URL. Otherwise:
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
gh pr list --repo {owner}/{repo} --state open --limit 1
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
### Step 2: Read comment threads
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
gh pr view {pr-number} --repo {owner}/{repo} --comments
|
|
18
|
+
# Or structured output:
|
|
19
|
+
gh api repos/{owner}/{repo}/pulls/{pr-number}/comments
|
|
20
|
+
gh api repos/{owner}/{repo}/pulls/{pr-number}/reviews
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### Step 3: Categorize feedback
|
|
24
|
+
|
|
25
|
+
| Category | Description | Action |
|
|
26
|
+
| ------------- | ----------------------------------- | ----------------------------------- |
|
|
27
|
+
| `code-change` | Reviewer requests code modification | Return to lead to spawn specialists |
|
|
28
|
+
| `spec-update` | Affects proposal, design, or tasks | Update openspec artifacts |
|
|
29
|
+
| `question` | Reviewer asks a question | Reply with answer |
|
|
30
|
+
| `resolved` | Thread already resolved | Skip |
|
|
31
|
+
|
|
32
|
+
### Step 4: Update openspec (if spec-update)
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
git branch --show-current
|
|
36
|
+
# feature/add-user-auth → change: add-user-auth
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Update: `openspec/changes/{change}/proposal.md`, `design.md`, or `tasks.md` as appropriate.
|
|
40
|
+
|
|
41
|
+
### Step 5: Reply to each comment thread
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
# Reply to a review comment
|
|
45
|
+
gh api repos/{owner}/{repo}/pulls/{pr-number}/comments/{comment-id}/replies \
|
|
46
|
+
--method POST \
|
|
47
|
+
--field body="Acknowledged, applying this change now."
|
|
48
|
+
|
|
49
|
+
# Or post a general PR comment
|
|
50
|
+
gh pr comment {pr-number} --body "Updated design.md to reflect feedback."
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
---
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
**ALL GitLab data MUST come from `glab` CLI. NEVER use webfetch, HTTP requests, or browser MCP tools for GitLab operations, even if glab CLI fails. If `glab` is unavailable, report as a blocker.**
|
|
2
|
+
Always pass `--repo {owner}/{repo}` explicitly, never rely on git context to resolve the repo.
|
|
3
|
+
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
### Step 1: Parse MR URL or number
|
|
7
|
+
|
|
8
|
+
- `https://gitlab.com/{owner}/{repo}/-/merge_requests/123` → MR !123, repo: `{owner}/{repo}`
|
|
9
|
+
- `https://gitlab.com/{owner}/{repo}/-/merge_requests/123#note_456` → MR !123, note: 456
|
|
10
|
+
- `!123` → MR !123
|
|
11
|
+
|
|
12
|
+
### Step 2: Fetch MR details and comments
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
glab mr view {number} --repo {owner}/{repo}
|
|
16
|
+
glab mr note list {number} --repo {owner}/{repo}
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Also fetch MR threads (inline code comments):
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
glab api "projects/:id/merge_requests/{number}/discussions"
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### Step 3: Classify comments
|
|
26
|
+
|
|
27
|
+
Categorize each comment as:
|
|
28
|
+
- **BLOCKER**: must fix before merge (test failures, security issues, broken logic)
|
|
29
|
+
- **IMPORTANT**: should fix (missing edge case, code quality, performance)
|
|
30
|
+
- **SUGGESTION**: nice to have (style, refactor, docs)
|
|
31
|
+
- **QUESTION**: needs clarification (respond or discuss)
|
|
32
|
+
- **RESOLVED**: already addressed or invalid
|
|
33
|
+
|
|
34
|
+
### Step 4: Report
|
|
35
|
+
|
|
36
|
+
Display a structured summary:
|
|
37
|
+
|
|
38
|
+
```text
|
|
39
|
+
MR Feedback Summary: !{number}
|
|
40
|
+
|
|
41
|
+
Blockers: {count}
|
|
42
|
+
[B1] {comment-author}: {comment-summary}
|
|
43
|
+
Important: {count}
|
|
44
|
+
[I1] {comment-author}: {comment-summary}
|
|
45
|
+
Suggestions: {count}
|
|
46
|
+
[S1] {comment-author}: {comment-summary}
|
|
47
|
+
Questions: {count}
|
|
48
|
+
[Q1] {comment-author}: {comment-summary}
|
|
49
|
+
|
|
50
|
+
Next: Run /plan-apply to fix blockers and important items.
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### Step 5: Do NOT implement fixes
|
|
54
|
+
|
|
55
|
+
This mode only triages. Fixing is done via `/plan-apply`. Tell the user what needs fixing, then stop.
|
|
56
|
+
|
|
57
|
+
---
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
**Browser MCP tools are FORBIDDEN for all Azure DevOps operations.**
|
|
2
|
+
Browser tools are ONLY permitted for screenshots of the LOCAL running app on `localhost` URLs.
|
|
3
|
+
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
### Step 1: Verify feature branch
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
git branch --show-current
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Branch must be `feature/{id}-{slug}`. NEVER push to `main`.
|
|
13
|
+
|
|
14
|
+
### Step 2: Capture screenshots (if UI changes exist)
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
browser_navigate url="http://localhost:{port}/{route}"
|
|
18
|
+
browser_wait ms=2000
|
|
19
|
+
browser_screenshot
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Save to: `openspec/changes/{change-name}/images/{feature}.png`
|
|
23
|
+
|
|
24
|
+
### Step 3: Commit and push
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
git add .
|
|
28
|
+
git commit -m "feat({scope}): {description} (#{id})"
|
|
29
|
+
git push origin feature/{id}-{slug}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### Step 4: Create PR
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
az repos pr create \
|
|
36
|
+
--repository {repo} \
|
|
37
|
+
--source-branch feature/{id}-{slug} \
|
|
38
|
+
--target-branch main \
|
|
39
|
+
--title "feat({scope}): {title} (#{id})" \
|
|
40
|
+
--description "{description}"
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Step 5: Link work item (MANDATORY, run sequentially, not in parallel)
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
az repos pr work-item add --id {pr-id} --work-items {workitem-id}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Step 6: Post screenshot comment
|
|
50
|
+
|
|
51
|
+
Build raw URL for each image:
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
https://dev.azure.com/{org}/{project}/_apis/git/repositories/{repo}/items?path=openspec/changes/{change}/images/{file}.png&versionType=branch&version={branch}&api-version=7.1
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Post via:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
az devops invoke \
|
|
61
|
+
--area git --resource pullRequestThreads \
|
|
62
|
+
--route-parameters project={project} repositoryId={repo} pullRequestId={pr-id} \
|
|
63
|
+
--http-method POST --api-version 7.1 --in-file body.json
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
`body.json`:
|
|
67
|
+
|
|
68
|
+
```json
|
|
69
|
+
{
|
|
70
|
+
"comments": [
|
|
71
|
+
{
|
|
72
|
+
"parentCommentId": 0,
|
|
73
|
+
"content": "## Screenshots\n\n",
|
|
74
|
+
"commentType": 1
|
|
75
|
+
}
|
|
76
|
+
],
|
|
77
|
+
"status": "active"
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
---
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
**ALL GitHub data MUST come from `gh` CLI. NEVER use webfetch, HTTP requests, or browser MCP tools for GitHub operations, even if gh CLI fails. If `gh` is unavailable, report as a blocker.**
|
|
2
|
+
Always pass `--repo {owner}/{repo}` explicitly, never rely on git context to resolve the repo.
|
|
3
|
+
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
### Step 1: Verify feature branch
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
BRANCH="$(git branch --show-current)"
|
|
10
|
+
DEFAULT_BRANCH="$(git symbolic-ref --short refs/remotes/origin/HEAD 2>/dev/null | sed 's|^origin/||')"
|
|
11
|
+
[ -z "$DEFAULT_BRANCH" ] && DEFAULT_BRANCH="main"
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
`$BRANCH` must be a work branch (`feature/*` or `bugfix/*`: the `pc-plan-apply` skill creates `feature/{change-slug}`). NEVER push the default branch.
|
|
15
|
+
|
|
16
|
+
### Step 2: Capture screenshots (if UI changes exist)
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
browser_navigate url="http://localhost:{port}/{route}"
|
|
20
|
+
browser_wait ms=2000
|
|
21
|
+
browser_screenshot
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Save to: `openspec/changes/{change-name}/images/{feature}.png`
|
|
25
|
+
|
|
26
|
+
### Step 3: Commit and push
|
|
27
|
+
|
|
28
|
+
The `pc-plan-apply` skill already committed each task group: usually only screenshots or small residuals remain. Stage **specific paths only** (never `git add .`, it sweeps unrelated files into the ship commit):
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
git add openspec/changes/{change-name}/images/ # plus any other paths you actually changed
|
|
32
|
+
git commit -m "feat({scope}): {description} (#{id})" # only if there is something to commit
|
|
33
|
+
git push -u origin "$BRANCH"
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### Step 4: Create PR
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
gh pr create \
|
|
40
|
+
--repo {owner}/{repo} \
|
|
41
|
+
--base "$DEFAULT_BRANCH" \
|
|
42
|
+
--head "$BRANCH" \
|
|
43
|
+
--title "feat({scope}): {title} (#{id})" \
|
|
44
|
+
--body "{description}"
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### Step 5: Post screenshot comment
|
|
48
|
+
|
|
49
|
+
Resolve commit SHA (the commit that includes screenshots):
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
git rev-parse HEAD
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Build blob URL for each image with `?raw=true` (a plain blob URL renders the GitHub HTML page, not the image, inside `![...]()`):
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
https://github.com/{owner}/{repo}/blob/{sha}/openspec/changes/{change}/images/{file}.png?raw=true
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Note: on private repos the embedded image is only visible to users with repo access.
|
|
62
|
+
|
|
63
|
+
Post comment:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
gh pr comment {pr-number} --repo {owner}/{repo} --body $'## Screenshots\n\n'
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
---
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
**ALL GitLab data MUST come from `glab` CLI. NEVER use webfetch, HTTP requests, or browser MCP tools for GitLab operations, even if glab CLI fails. If `glab` is unavailable, report as a blocker.**
|
|
2
|
+
Always pass `--repo {owner}/{repo}` explicitly, never rely on git context to resolve the repo.
|
|
3
|
+
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
### Step 1: Verify feature branch
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
BRANCH="$(git branch --show-current)"
|
|
10
|
+
DEFAULT_BRANCH="$(git symbolic-ref --short refs/remotes/origin/HEAD 2>/dev/null | sed 's|^origin/||')"
|
|
11
|
+
[ -z "$DEFAULT_BRANCH" ] && DEFAULT_BRANCH="main"
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
`$BRANCH` must be a work branch (`feature/*` or `bugfix/*`: the `pc-plan-apply` skill creates `feature/{change-slug}`). NEVER push the default branch.
|
|
15
|
+
|
|
16
|
+
### Step 2: Capture screenshots (if UI changes exist)
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
browser_navigate url="http://localhost:{port}/{route}"
|
|
20
|
+
browser_wait ms=2000
|
|
21
|
+
browser_screenshot
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Save to: `openspec/changes/{change-name}/images/{feature}.png`
|
|
25
|
+
|
|
26
|
+
### Step 3: Commit and push
|
|
27
|
+
|
|
28
|
+
The `pc-plan-apply` skill already committed each task group: usually only screenshots or small residuals remain. Stage **specific paths only** (never `git add -A`, it sweeps unrelated files into the ship commit):
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
git add openspec/changes/{change-name}/images/ # plus any other paths you actually changed
|
|
32
|
+
git commit -m "{change}: {summary}" # only if there is something to commit
|
|
33
|
+
git push -u origin "$BRANCH"
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### Step 4: Upload screenshots (if any)
|
|
37
|
+
|
|
38
|
+
If screenshots exist, upload them so they can be referenced in the MR description:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
glab api --method POST "projects/:id/uploads" -f "file=@openspec/changes/{change-name}/images/{feature}.png"
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
(`:id` is glab's placeholder for the current project: this is the one sanctioned use of git context in this skill.)
|
|
45
|
+
|
|
46
|
+
Parse the returned `markdown` field: use it to embed the image in the MR description. If the upload fails (the endpoint needs multipart form data and `-f` support varies by glab version), fall back to referencing the image committed on the branch instead.
|
|
47
|
+
|
|
48
|
+
If no UI changes, skip this step.
|
|
49
|
+
|
|
50
|
+
### Step 5: Create Merge Request
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
glab mr create \
|
|
54
|
+
--source-branch "$BRANCH" \
|
|
55
|
+
--target-branch "$DEFAULT_BRANCH" \
|
|
56
|
+
--title "{title}" \
|
|
57
|
+
--description "Closes {issue-link}
|
|
58
|
+
|
|
59
|
+
## Summary
|
|
60
|
+
{summary from proposal.md}
|
|
61
|
+
|
|
62
|
+
## Changes
|
|
63
|
+
{key changes from tasks.md}
|
|
64
|
+
|
|
65
|
+
## Test plan
|
|
66
|
+
- [ ] {checklist of manual verification steps}
|
|
67
|
+
{screenshots if available}" \
|
|
68
|
+
--remove-source-branch \
|
|
69
|
+
--squash-before-merge
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Do NOT use `--yes` unless running in autopilot/non-interactive mode.
|
|
73
|
+
|
|
74
|
+
### Step 6: Report
|
|
75
|
+
|
|
76
|
+
Display:
|
|
77
|
+
|
|
78
|
+
```text
|
|
79
|
+
Merge Request created
|
|
80
|
+
MR: {mr-url}
|
|
81
|
+
Title: {title}
|
|
82
|
+
Source: {branch}
|
|
83
|
+
Target: {default-branch}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
---
|
package/src/index.js
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import chalk from 'chalk'
|
|
3
|
+
import { createRequire } from 'node:module'
|
|
4
|
+
import { runJoin } from './commands/join.js'
|
|
5
|
+
import { runUpdate } from './commands/update.js'
|
|
6
|
+
import { runSingleCommand } from './commands/single.js'
|
|
7
|
+
import { runWizard } from './commands/wizard.js'
|
|
8
|
+
import { exit } from './utils/process.js'
|
|
9
|
+
import { findLegacyInstall } from './utils/legacy-check.js'
|
|
10
|
+
|
|
11
|
+
function printHelp(version) {
|
|
12
|
+
console.log(`agent-harness v${version}`)
|
|
13
|
+
console.log()
|
|
14
|
+
console.log('Usage:')
|
|
15
|
+
console.log(' npx @plainconceptsplatform/agent-harness Install the harness (full wizard)')
|
|
16
|
+
console.log(' npx @plainconceptsplatform/agent-harness <command> Run a single step command')
|
|
17
|
+
console.log()
|
|
18
|
+
console.log('Commands:')
|
|
19
|
+
console.log(' update Bring the harness up to date from saved config (no prompts)')
|
|
20
|
+
console.log(' join Set up a teammate\'s machine (checks & local installs only)')
|
|
21
|
+
console.log(' clean Run AI files cleanup step')
|
|
22
|
+
console.log(' platform Run platform selection step')
|
|
23
|
+
console.log(' copy Run content copy step')
|
|
24
|
+
console.log(' openspec Run OpenSpec initialization step')
|
|
25
|
+
console.log(' models Run models selection step')
|
|
26
|
+
console.log(' optimization Run token optimization tools step')
|
|
27
|
+
console.log(' browser Run opencode-browser installer step')
|
|
28
|
+
console.log(' metadata Write onboarding metadata step')
|
|
29
|
+
console.log()
|
|
30
|
+
console.log('Options:')
|
|
31
|
+
console.log(' -h, --help Show this help message')
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (process.stdout.isTTY) console.clear()
|
|
35
|
+
console.log()
|
|
36
|
+
const require = createRequire(import.meta.url)
|
|
37
|
+
const { version } = require('../package.json')
|
|
38
|
+
const args = process.argv.slice(2)
|
|
39
|
+
|
|
40
|
+
if (args.includes('-h') || args.includes('--help')) {
|
|
41
|
+
printHelp(version)
|
|
42
|
+
exit()
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async function refuseLegacyInstall() {
|
|
46
|
+
const legacy = await findLegacyInstall()
|
|
47
|
+
if (!legacy) return false
|
|
48
|
+
|
|
49
|
+
console.log(chalk.red('This project was set up by opencode-onboard v1.'))
|
|
50
|
+
console.log()
|
|
51
|
+
if (legacy.files.length > 0) console.log(chalk.dim(` config: ${legacy.files.join(', ')}`))
|
|
52
|
+
if (legacy.skills.length > 0) {
|
|
53
|
+
const shown = legacy.skills.slice(0, 3).join(', ')
|
|
54
|
+
const rest = legacy.skills.length > 3 ? `, +${legacy.skills.length - 3} more` : ''
|
|
55
|
+
console.log(chalk.dim(` skills: ${shown}${rest}`))
|
|
56
|
+
}
|
|
57
|
+
console.log()
|
|
58
|
+
console.log('agent-harness v2 renamed both the config files and the skill prefix,')
|
|
59
|
+
console.log('and it does not migrate v1 projects. Continuing would leave the harness')
|
|
60
|
+
console.log('half-patched without reporting an error.')
|
|
61
|
+
console.log()
|
|
62
|
+
console.log('Re-onboard on a clean branch instead:')
|
|
63
|
+
console.log(chalk.dim(' git switch -c chore/agent-harness'))
|
|
64
|
+
console.log(chalk.dim(' rm -rf .opencode .agents/skills/ob-*'))
|
|
65
|
+
console.log(chalk.dim(' npx @plainconceptsplatform/agent-harness'))
|
|
66
|
+
return true
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// Ctrl-C out of an @inquirer prompt throws ExitPromptError; that is a normal
|
|
70
|
+
// cancellation, not a crash, so it must not exit non-zero.
|
|
71
|
+
async function main() {
|
|
72
|
+
if (await refuseLegacyInstall()) {
|
|
73
|
+
exit(1)
|
|
74
|
+
return
|
|
75
|
+
}
|
|
76
|
+
if (args.length === 0) {
|
|
77
|
+
await runWizard(version)
|
|
78
|
+
return
|
|
79
|
+
}
|
|
80
|
+
if (args[0] === 'join') {
|
|
81
|
+
await runJoin()
|
|
82
|
+
return
|
|
83
|
+
}
|
|
84
|
+
if (args[0] === 'update') {
|
|
85
|
+
await runUpdate()
|
|
86
|
+
return
|
|
87
|
+
}
|
|
88
|
+
if (!await runSingleCommand(args[0])) {
|
|
89
|
+
console.log(chalk.red(`Unknown command: ${args[0]}`))
|
|
90
|
+
console.log()
|
|
91
|
+
printHelp(version)
|
|
92
|
+
exit(1)
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
try {
|
|
97
|
+
await main()
|
|
98
|
+
} catch (err) {
|
|
99
|
+
if (err.name === 'ExitPromptError') {
|
|
100
|
+
console.log()
|
|
101
|
+
console.log(chalk.yellow('Cancelled.'))
|
|
102
|
+
} else {
|
|
103
|
+
console.error(chalk.red('\nUnexpected error:'), err.message)
|
|
104
|
+
exit(1)
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
exit()
|