@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.
Files changed (155) hide show
  1. package/README.md +23 -12
  2. package/{src → cli}/commands/join.js +3 -4
  3. package/{src → cli}/commands/migrate.js +1 -1
  4. package/{src → cli}/commands/update.js +13 -1
  5. package/{src → cli}/commands/wizard.js +1 -1
  6. package/{src → cli}/index.js +1 -1
  7. package/{src → cli}/presets/agents-content.json +4 -4
  8. package/cli/presets/browser.json +10 -0
  9. package/{src → cli}/presets/clean.json +21 -21
  10. package/{src → cli}/presets/optimization.json +37 -37
  11. package/{src → cli}/presets/platforms.json +76 -76
  12. package/{src → cli}/presets/quota.json +16 -16
  13. package/{src → cli}/presets/source.json +23 -23
  14. package/cli/steps/browser/index.js +48 -0
  15. package/{src → cli}/steps/clean/index.js +120 -120
  16. package/{src → cli}/steps/copy/agents.js +119 -119
  17. package/{src → cli}/steps/copy/commands.js +95 -95
  18. package/{src → cli}/steps/copy/fullstack-engineer.js +5 -1
  19. package/{src → cli}/steps/copy/index.js +1 -1
  20. package/{src → cli}/steps/copy/opencode-json.js +50 -1
  21. package/{src → cli}/steps/copy/skills.js +2 -2
  22. package/{src → cli}/steps/metadata/index.js +4 -0
  23. package/{src → cli}/steps/models/format.js +88 -88
  24. package/{src → cli}/steps/models/index.js +64 -64
  25. package/{src → cli}/steps/openspec/index.js +136 -136
  26. package/{src → cli}/steps/optimization/codegraph.js +127 -127
  27. package/cli/steps/optimization/detect.js +66 -0
  28. package/{src → cli}/steps/optimization/humanizer.js +17 -17
  29. package/{src → cli}/steps/optimization/index.js +163 -163
  30. package/{src → cli}/steps/optimization/memory.js +88 -88
  31. package/{src → cli}/steps/optimization/patch-guardrails.js +109 -109
  32. package/{src → cli}/steps/optimization/quota.js +119 -119
  33. package/{src → cli}/steps/optimization/simple-english.js +17 -17
  34. package/{src → cli}/steps/optimization/skills-lock.js +30 -30
  35. package/{src → cli}/steps/platform/index.js +109 -109
  36. package/{src → cli}/steps/source/index.js +123 -123
  37. package/cli/utils/agent-color.js +111 -0
  38. package/{src → cli}/utils/exec-spinner.js +47 -47
  39. package/{src → cli}/utils/exec.js +134 -134
  40. package/{src → cli}/utils/models-pricing.js +42 -42
  41. package/{src → cli}/utils/paths.js +1 -1
  42. package/{src → cli}/utils/process.js +3 -3
  43. package/{src → cli}/utils/terminal.js +6 -6
  44. package/harness/.agents/skills/browser-automation/SKILL.md +72 -0
  45. package/{src/content → harness}/.agents/skills/pc-make-engineer/SKILL.md +1 -1
  46. package/{src/content → harness}/.agents/skills/pc-make-engineer/template.md +1 -2
  47. package/{src/content → harness}/.agents/skills/pc-plan-archive/SKILL.md +3 -0
  48. package/{src/content → harness}/.agents/skills/pc-plan-explore/SKILL.md +3 -0
  49. package/{src/content → harness}/.agents/skills/pc-plan-goal/SKILL.md +5 -16
  50. package/{src/content → harness}/.agents/skills/pc-plan-goal/branching.md +1 -1
  51. package/{src/content → harness}/.agents/skills/pc-plan-goal/output.md +5 -8
  52. package/{src/content → harness}/.agents/skills/pc-plan-story/SKILL.md +3 -0
  53. package/{src/content → harness}/.agents/skills/pc-userstory-browser/SKILL.md +136 -132
  54. package/{src/content → harness}/.opencode/package.json +9 -10
  55. package/{src/content → harness}/.opencode/plugins/pc-subagent-tiers.js +91 -4
  56. package/{src/content → harness}/ARCHITECTURE.md +16 -16
  57. package/{src/content → harness}/DESIGN.md +16 -16
  58. package/{src/content → harness}/opencode.jsonc +11 -3
  59. package/{src/content → harness}/openspec/config.yaml +20 -20
  60. package/{src/content → harness}/skills-lock.json +17 -17
  61. package/package.json +7 -7
  62. package/src/content/.agents/skills/browser-automation/SKILL.md +0 -66
  63. package/src/presets/browser.json +0 -22
  64. package/src/steps/browser/index.js +0 -91
  65. /package/{src → cli}/commands/shared.js +0 -0
  66. /package/{src → cli}/commands/single.js +0 -0
  67. /package/{src → cli}/fragments/archive/az.md +0 -0
  68. /package/{src → cli}/fragments/archive/gh.md +0 -0
  69. /package/{src → cli}/fragments/archive/gl.md +0 -0
  70. /package/{src → cli}/fragments/archive/none.md +0 -0
  71. /package/{src → cli}/fragments/guardrails/codegraph.md +0 -0
  72. /package/{src → cli}/fragments/guardrails/humanizer.md +0 -0
  73. /package/{src → cli}/fragments/guardrails/memory.md +0 -0
  74. /package/{src → cli}/fragments/guardrails/rtk.md +0 -0
  75. /package/{src → cli}/fragments/guardrails/simple-english.md +0 -0
  76. /package/{src → cli}/fragments/ops-backlog/az.md +0 -0
  77. /package/{src → cli}/fragments/ops-backlog/gh.md +0 -0
  78. /package/{src → cli}/fragments/ops-backlog/jira.md +0 -0
  79. /package/{src → cli}/fragments/ops-evidence/az.md +0 -0
  80. /package/{src → cli}/fragments/ops-evidence/gh.md +0 -0
  81. /package/{src → cli}/fragments/ops-evidence/jira.md +0 -0
  82. /package/{src → cli}/fragments/ops-review/az.md +0 -0
  83. /package/{src → cli}/fragments/ops-review/gh.md +0 -0
  84. /package/{src → cli}/fragments/ops-review/gl.md +0 -0
  85. /package/{src → cli}/fragments/ops-ship/az.md +0 -0
  86. /package/{src → cli}/fragments/ops-ship/gh.md +0 -0
  87. /package/{src → cli}/fragments/ops-ship/gl.md +0 -0
  88. /package/{src → cli}/presets/models.json +0 -0
  89. /package/{src → cli}/presets/openspec.json +0 -0
  90. /package/{src → cli}/steps/models/write.js +0 -0
  91. /package/{src → cli}/utils/copy.js +0 -0
  92. /package/{src → cli}/utils/legacy-check.js +0 -0
  93. /package/{src → cli}/utils/models-cache.js +0 -0
  94. /package/{src → cli}/utils/update-manifest.js +0 -0
  95. /package/{src/content → harness}/.agents/skills/pc-guardrails-generic/SKILL.md +0 -0
  96. /package/{src/content → harness}/.agents/skills/pc-guardrails-project/SKILL.md +0 -0
  97. /package/{src/content → harness}/.agents/skills/pc-make-architecture/SKILL.md +0 -0
  98. /package/{src/content → harness}/.agents/skills/pc-make-architecture/structure-template.md +0 -0
  99. /package/{src/content → harness}/.agents/skills/pc-make-design/SKILL.md +0 -0
  100. /package/{src/content → harness}/.agents/skills/pc-make-engineer/signal-mapping.md +0 -0
  101. /package/{src/content → harness}/.agents/skills/pc-make-evidence-scaffold/SKILL.md +0 -0
  102. /package/{src/content → harness}/.agents/skills/pc-make-evidence-scaffold/evidence-contract.md +0 -0
  103. /package/{src/content → harness}/.agents/skills/pc-make-guardrails/SKILL.md +0 -0
  104. /package/{src/content → harness}/.agents/skills/pc-make-guardrails/category-reference.md +0 -0
  105. /package/{src/content → harness}/.agents/skills/pc-make-merge-risk-assess/SKILL.md +0 -0
  106. /package/{src/content → harness}/.agents/skills/pc-make-merge-risk-assess/category-reference.md +0 -0
  107. /package/{src/content → harness}/.agents/skills/pc-make-user-model/SKILL.md +0 -0
  108. /package/{src/content → harness}/.agents/skills/pc-ops-evidence/SKILL.md +0 -0
  109. /package/{src/content → harness}/.agents/skills/pc-ops-ship/SKILL.md +0 -0
  110. /package/{src/content → harness}/.agents/skills/pc-plan-apply/SKILL.md +0 -0
  111. /package/{src/content → harness}/.agents/skills/pc-plan-apply/simple-mode.md +0 -0
  112. /package/{src/content → harness}/.agents/skills/pc-plan-goal/failure-policy.md +0 -0
  113. /package/{src/content → harness}/.agents/skills/pc-plan-goal/output-mode.md +0 -0
  114. /package/{src/content → harness}/.agents/skills/pc-plan-propose/SKILL.md +0 -0
  115. /package/{src/content → harness}/.agents/skills/pc-plan-propose/task-annotation.md +0 -0
  116. /package/{src/content → harness}/.agents/skills/pc-plan-quick/SKILL.md +0 -0
  117. /package/{src/content → harness}/.agents/skills/pc-repo-audit/SKILL.md +0 -0
  118. /package/{src/content → harness}/.agents/skills/pc-repo-help/SKILL.md +0 -0
  119. /package/{src/content → harness}/.agents/skills/pc-repo-initialize/SKILL.md +0 -0
  120. /package/{src/content → harness}/.agents/skills/pc-repo-onboard/SKILL.md +0 -0
  121. /package/{src/content → harness}/.agents/skills/pc-repo-verify/SKILL.md +0 -0
  122. /package/{src/content → harness}/.agents/skills/pc-userstory-az/SKILL.md +0 -0
  123. /package/{src/content → harness}/.agents/skills/pc-userstory-gh/SKILL.md +0 -0
  124. /package/{src/content → harness}/.agents/skills/pc-userstory-jira/SKILL.md +0 -0
  125. /package/{src/content → harness}/.opencode/_gitignore +0 -0
  126. /package/{src/content → harness}/.opencode/commands/init.md +0 -0
  127. /package/{src/content → harness}/.opencode/commands/make-architecture.md +0 -0
  128. /package/{src/content → harness}/.opencode/commands/make-design.md +0 -0
  129. /package/{src/content → harness}/.opencode/commands/make-engineer.md +0 -0
  130. /package/{src/content → harness}/.opencode/commands/make-evidence-scaffold.md +0 -0
  131. /package/{src/content → harness}/.opencode/commands/make-guardrails.md +0 -0
  132. /package/{src/content → harness}/.opencode/commands/make-user-model.md +0 -0
  133. /package/{src/content → harness}/.opencode/commands/ops-backlog.md +0 -0
  134. /package/{src/content → harness}/.opencode/commands/ops-evidence.md +0 -0
  135. /package/{src/content → harness}/.opencode/commands/ops-review.md +0 -0
  136. /package/{src/content → harness}/.opencode/commands/ops-ship.md +0 -0
  137. /package/{src/content → harness}/.opencode/commands/plan-apply.md +0 -0
  138. /package/{src/content → harness}/.opencode/commands/plan-archive.md +0 -0
  139. /package/{src/content → harness}/.opencode/commands/plan-explore.md +0 -0
  140. /package/{src/content → harness}/.opencode/commands/plan-goal.md +0 -0
  141. /package/{src/content → harness}/.opencode/commands/plan-propose.md +0 -0
  142. /package/{src/content → harness}/.opencode/commands/plan-quick.md +0 -0
  143. /package/{src/content → harness}/.opencode/commands/plan-story.md +0 -0
  144. /package/{src/content → harness}/.opencode/commands/repo-audit.md +0 -0
  145. /package/{src/content → harness}/.opencode/commands/repo-help.md +0 -0
  146. /package/{src/content → harness}/.opencode/commands/repo-initialize.md +0 -0
  147. /package/{src/content → harness}/.opencode/commands/repo-onboard.md +0 -0
  148. /package/{src/content → harness}/.opencode/commands/repo-verify.md +0 -0
  149. /package/{src/content → harness}/.opencode/plugins/pc-subagent-monitor.js +0 -0
  150. /package/{src/content → harness}/.opencode/plugins/pc-system-reminders.js +0 -0
  151. /package/{src/content → harness}/.opencode/tui/pc-subagents.tsx +0 -0
  152. /package/{src/content → harness}/.opencode/tui.json +0 -0
  153. /package/{src/content → harness}/AGENTS.md +0 -0
  154. /package/{src/content → harness}/openspec/changes/archive/.gitkeep +0 -0
  155. /package/{src/content → harness}/openspec/specs/.gitkeep +0 -0
@@ -1,134 +1,134 @@
1
- import chalk from 'chalk'
2
- import { execa } from 'execa'
3
- import ora from 'ora'
4
- import { appendLine, redraw, rotateStep, startSpinner, stopSpinner } from './exec-spinner.js'
5
- import { MARKERS } from './terminal.js';
6
-
7
- // ── Public API ───────────────────────────────────────────────────────────────
8
-
9
- /**
10
- * Run a shell command with a spinner.
11
- * Returns { success, stdout, stderr }
12
- */
13
- export async function run(command, args = [], { label, cwd = process.cwd() } = {}) {
14
- const spinner = ora(label ?? `${command} ${args.join(' ')}`).start();
15
- try {
16
- const result = await execa(command, args, { cwd, reject: false });
17
- if (result.exitCode === 0) {
18
- spinner.succeed();
19
- } else {
20
- spinner.fail();
21
- }
22
- return { success: result.exitCode === 0, stdout: result.stdout, stderr: result.stderr };
23
- } catch (err) {
24
- spinner.fail();
25
- return { success: false, stdout: '', stderr: err.message };
26
- }
27
- }
28
-
29
- /**
30
- * Check if a command is available on PATH.
31
- * Returns true/false.
32
- */
33
- export async function commandExists(command) {
34
- try {
35
- const result = await execa(command, ['--version'], { reject: false });
36
- return result.exitCode === 0;
37
- } catch {
38
- return false;
39
- }
40
- }
41
-
42
- /**
43
- * Print a section header, clears screen, shows previous step dimmed, starts new step.
44
- */
45
- export function header(text) {
46
- rotateStep();
47
-
48
- const line1 = '';
49
- const line2 = chalk.bold.hex('#fe3d57')(`━━ ${text}`);
50
- const line3 = '';
51
-
52
- appendLine(line1);
53
- appendLine(line2);
54
- appendLine(line3);
55
-
56
- redraw();
57
-
58
- startSpinner('working...');
59
- }
60
-
61
- /**
62
- * Restart the step spinner after prompts or logs.
63
- */
64
- export function loading(text = 'working...') {
65
- startSpinner(text);
66
- }
67
-
68
- /**
69
- * Print a success line.
70
- */
71
- export function success(text) {
72
- stopSpinner();
73
- const line = chalk.green(`${MARKERS.OK_PREFIX}${text}`);
74
- appendLine(line);
75
- console.log(line);
76
- }
77
-
78
- /**
79
- * Print a warning line.
80
- */
81
- export function warn(text) {
82
- stopSpinner();
83
- const line = chalk.yellow(`${MARKERS.WARN_PREFIX}${text}`);
84
- appendLine(line);
85
- console.log(line);
86
- }
87
-
88
- /**
89
- * Print an error line.
90
- */
91
- export function error(text) {
92
- stopSpinner();
93
- const line = chalk.red(`${MARKERS.ERROR_PREFIX}${text}`);
94
- appendLine(line);
95
- console.log(line);
96
- }
97
-
98
- /**
99
- * Print an info line.
100
- */
101
- export function info(text) {
102
- stopSpinner();
103
- const line = chalk.dim(`${MARKERS.EMPTY}${text}`);
104
- appendLine(line);
105
- console.log(line);
106
- }
107
-
108
- /**
109
- * Print an action prompt line (white bold, requires user interaction).
110
- */
111
- export function prompt(text) {
112
- stopSpinner();
113
- const line = chalk.bold(`${MARKERS.EMPTY}${text}`);
114
- appendLine(line);
115
- console.log(line);
116
- }
117
-
118
- /**
119
- * Print a code block.
120
- */
121
- export function code(lines) {
122
- stopSpinner();
123
- appendLine('');
124
- console.log();
125
- for (const line of lines) {
126
- const formatted = chalk.bgGray.white(
127
- `${MARKERS.EMPTY}${line}${MARKERS.EMPTY}`,
128
- );
129
- appendLine(formatted);
130
- console.log(formatted);
131
- }
132
- appendLine('');
133
- console.log();
134
- }
1
+ import chalk from 'chalk'
2
+ import { execa } from 'execa'
3
+ import ora from 'ora'
4
+ import { appendLine, redraw, rotateStep, startSpinner, stopSpinner } from './exec-spinner.js'
5
+ import { MARKERS } from './terminal.js';
6
+
7
+ // ── Public API ───────────────────────────────────────────────────────────────
8
+
9
+ /**
10
+ * Run a shell command with a spinner.
11
+ * Returns { success, stdout, stderr }
12
+ */
13
+ export async function run(command, args = [], { label, cwd = process.cwd() } = {}) {
14
+ const spinner = ora(label ?? `${command} ${args.join(' ')}`).start();
15
+ try {
16
+ const result = await execa(command, args, { cwd, reject: false });
17
+ if (result.exitCode === 0) {
18
+ spinner.succeed();
19
+ } else {
20
+ spinner.fail();
21
+ }
22
+ return { success: result.exitCode === 0, stdout: result.stdout, stderr: result.stderr };
23
+ } catch (err) {
24
+ spinner.fail();
25
+ return { success: false, stdout: '', stderr: err.message };
26
+ }
27
+ }
28
+
29
+ /**
30
+ * Check if a command is available on PATH.
31
+ * Returns true/false.
32
+ */
33
+ export async function commandExists(command) {
34
+ try {
35
+ const result = await execa(command, ['--version'], { reject: false });
36
+ return result.exitCode === 0;
37
+ } catch {
38
+ return false;
39
+ }
40
+ }
41
+
42
+ /**
43
+ * Print a section header, clears screen, shows previous step dimmed, starts new step.
44
+ */
45
+ export function header(text) {
46
+ rotateStep();
47
+
48
+ const line1 = '';
49
+ const line2 = chalk.bold.hex('#fe3d57')(`━━ ${text}`);
50
+ const line3 = '';
51
+
52
+ appendLine(line1);
53
+ appendLine(line2);
54
+ appendLine(line3);
55
+
56
+ redraw();
57
+
58
+ startSpinner('working...');
59
+ }
60
+
61
+ /**
62
+ * Restart the step spinner after prompts or logs.
63
+ */
64
+ export function loading(text = 'working...') {
65
+ startSpinner(text);
66
+ }
67
+
68
+ /**
69
+ * Print a success line.
70
+ */
71
+ export function success(text) {
72
+ stopSpinner();
73
+ const line = chalk.green(`${MARKERS.OK_PREFIX}${text}`);
74
+ appendLine(line);
75
+ console.log(line);
76
+ }
77
+
78
+ /**
79
+ * Print a warning line.
80
+ */
81
+ export function warn(text) {
82
+ stopSpinner();
83
+ const line = chalk.yellow(`${MARKERS.WARN_PREFIX}${text}`);
84
+ appendLine(line);
85
+ console.log(line);
86
+ }
87
+
88
+ /**
89
+ * Print an error line.
90
+ */
91
+ export function error(text) {
92
+ stopSpinner();
93
+ const line = chalk.red(`${MARKERS.ERROR_PREFIX}${text}`);
94
+ appendLine(line);
95
+ console.log(line);
96
+ }
97
+
98
+ /**
99
+ * Print an info line.
100
+ */
101
+ export function info(text) {
102
+ stopSpinner();
103
+ const line = chalk.dim(`${MARKERS.EMPTY}${text}`);
104
+ appendLine(line);
105
+ console.log(line);
106
+ }
107
+
108
+ /**
109
+ * Print an action prompt line (white bold, requires user interaction).
110
+ */
111
+ export function prompt(text) {
112
+ stopSpinner();
113
+ const line = chalk.bold(`${MARKERS.EMPTY}${text}`);
114
+ appendLine(line);
115
+ console.log(line);
116
+ }
117
+
118
+ /**
119
+ * Print a code block.
120
+ */
121
+ export function code(lines) {
122
+ stopSpinner();
123
+ appendLine('');
124
+ console.log();
125
+ for (const line of lines) {
126
+ const formatted = chalk.bgGray.white(
127
+ `${MARKERS.EMPTY}${line}${MARKERS.EMPTY}`,
128
+ );
129
+ appendLine(formatted);
130
+ console.log(formatted);
131
+ }
132
+ appendLine('');
133
+ console.log();
134
+ }
@@ -1,42 +1,42 @@
1
- // Providers considered "canonical" for reference pricing, in priority order.
2
- // When a model's own provider has no cost (e.g. github-copilot shows $0),
3
- // we look up the same model name in these providers and attach canonicalCost.
4
- export const CANONICAL_PROVIDERS = ['anthropic', 'openai', 'google', 'mistral', 'meta', 'cohere'];
5
-
6
- export function parseModels(data) {
7
- // Build name → canonical cost lookup from authoritative providers first
8
- const canonicalCostByName = new Map();
9
- for (const providerId of CANONICAL_PROVIDERS) {
10
- const provider = data[providerId];
11
- if (!provider?.models) continue;
12
- for (const model of Object.values(provider.models)) {
13
- if (!model.tool_call) continue;
14
- const name = model.name;
15
- if (name && model.cost?.input !== undefined && !canonicalCostByName.has(name)) {
16
- canonicalCostByName.set(name, model.cost.input);
17
- }
18
- }
19
- }
20
-
21
- const models = [];
22
- for (const [providerId, provider] of Object.entries(data)) {
23
- if (!provider.models) continue;
24
- for (const [modelId, model] of Object.entries(provider.models)) {
25
- if (!model.tool_call) continue;
26
- const name = model.name || modelId;
27
- const cost = model.cost?.input;
28
- const canonicalCost = canonicalCostByName.get(name);
29
- models.push({
30
- id: `${providerId}/${modelId}`,
31
- name,
32
- cost,
33
- // canonicalCost: cost from the authoritative provider for this model name.
34
- // Defined when cost !== canonicalCost (different provider, reseller, or $0 subscription).
35
- canonicalCost: canonicalCost !== undefined && canonicalCost !== cost ? canonicalCost : undefined,
36
- context: model.limit?.context,
37
- });
38
- }
39
- }
40
- models.sort((a, b) => (a.cost ?? Infinity) - (b.cost ?? Infinity));
41
- return models;
42
- }
1
+ // Providers considered "canonical" for reference pricing, in priority order.
2
+ // When a model's own provider has no cost (e.g. github-copilot shows $0),
3
+ // we look up the same model name in these providers and attach canonicalCost.
4
+ export const CANONICAL_PROVIDERS = ['anthropic', 'openai', 'google', 'mistral', 'meta', 'cohere'];
5
+
6
+ export function parseModels(data) {
7
+ // Build name → canonical cost lookup from authoritative providers first
8
+ const canonicalCostByName = new Map();
9
+ for (const providerId of CANONICAL_PROVIDERS) {
10
+ const provider = data[providerId];
11
+ if (!provider?.models) continue;
12
+ for (const model of Object.values(provider.models)) {
13
+ if (!model.tool_call) continue;
14
+ const name = model.name;
15
+ if (name && model.cost?.input !== undefined && !canonicalCostByName.has(name)) {
16
+ canonicalCostByName.set(name, model.cost.input);
17
+ }
18
+ }
19
+ }
20
+
21
+ const models = [];
22
+ for (const [providerId, provider] of Object.entries(data)) {
23
+ if (!provider.models) continue;
24
+ for (const [modelId, model] of Object.entries(provider.models)) {
25
+ if (!model.tool_call) continue;
26
+ const name = model.name || modelId;
27
+ const cost = model.cost?.input;
28
+ const canonicalCost = canonicalCostByName.get(name);
29
+ models.push({
30
+ id: `${providerId}/${modelId}`,
31
+ name,
32
+ cost,
33
+ // canonicalCost: cost from the authoritative provider for this model name.
34
+ // Defined when cost !== canonicalCost (different provider, reseller, or $0 subscription).
35
+ canonicalCost: canonicalCost !== undefined && canonicalCost !== cost ? canonicalCost : undefined,
36
+ context: model.limit?.context,
37
+ });
38
+ }
39
+ }
40
+ models.sort((a, b) => (a.cost ?? Infinity) - (b.cost ?? Infinity));
41
+ return models;
42
+ }
@@ -6,7 +6,7 @@ import path from 'node:path'
6
6
  *
7
7
  * These filenames are a contract with every repo the harness has been
8
8
  * installed into: the CLI writes them, and the opencode plugins shipped in
9
- * src/content/.opencode/plugins/ read them back at runtime. Changing a name
9
+ * harness/.opencode/plugins/ read them back at runtime. Changing a name
10
10
  * here means changing it in that payload too, or the plugins go blind.
11
11
  *
12
12
  * They are deliberately named for the harness rather than for the CLI, so a
@@ -1,3 +1,3 @@
1
- export function exit(code = 0) {
2
- process.exit(code)
3
- }
1
+ export function exit(code = 0) {
2
+ process.exit(code)
3
+ }
@@ -1,6 +1,6 @@
1
- export const MARKERS = {
2
- EMPTY: " ",
3
- OK_PREFIX: "✓ ",
4
- WARN_PREFIX: "⚠ ",
5
- ERROR_PREFIX: "✗ ",
6
- };
1
+ export const MARKERS = {
2
+ EMPTY: " ",
3
+ OK_PREFIX: "✓ ",
4
+ WARN_PREFIX: "⚠ ",
5
+ ERROR_PREFIX: "✗ ",
6
+ };
@@ -0,0 +1,72 @@
1
+ ---
2
+ name: browser-automation
3
+ description: Reliable, composable browser automation using agent-browser. Use when capturing screenshots of a locally running app, clicking UI elements, reading page content, or automating browser interactions on localhost.
4
+ license: MIT
5
+ compatibility: Requires agent-browser CLI installed (Rust binary) and running.
6
+ metadata:
7
+ author: copilots
8
+ version: "2.0"
9
+ ---
10
+
11
+ This skill operates on `localhost` URLs only. Screenshots, clicks, typing, scrolling, and reads on locally running apps are in scope. External services (github.com, dev.azure.com, npmjs.com, etc.) are out of scope for browser tools.
12
+
13
+ The only exception: when the user selects "Others (Browser)" as their backlog platform during onboarding, the `pc-userstory` skill may navigate to work item URLs the user explicitly provides. That is the sole case where external navigation is permitted, and only to URLs the user explicitly gives you.
14
+
15
+ ## Best-practice workflow
16
+
17
+ 1. Open the page: `agent-browser open <url>` (launches its own Chrome; reuses the running daemon)
18
+ 2. Take a snapshot: `agent-browser snapshot` to get the accessibility tree with `@ref` handles
19
+ 3. Interact by ref: `agent-browser click @e2`, `agent-browser fill @e3 "text"`
20
+ 4. Wait when needed: `agent-browser wait --load networkidle` or `agent-browser wait <selector>`
21
+ 5. Confirm the result with a fresh `snapshot`, `get text`, or `screenshot`
22
+
23
+ Refs like `@e2` come from the last snapshot and go stale after page changes: retake the snapshot after navigation or dynamic updates before reusing them. When a click fails because another element covers the target (consent banner, modal), dismiss or interact with the covering element, then take a fresh snapshot before retrying.
24
+
25
+ ## Tool access
26
+
27
+ - MCP tools (inside OpenCode): `agent_browser_open`, `agent_browser_snapshot`, `agent_browser_click`, `agent_browser_fill`, `agent_browser_type`, `agent_browser_wait_for_selector`, `agent_browser_screenshot`, `agent_browser_eval`, `agent_browser_close` — configured in `opencode.jsonc` with `--tools core`
28
+ - CLI (any agent, any host): every command below works identically via bash
29
+ - Diagnose the install: `agent-browser doctor`
30
+
31
+ ## Selecting elements
32
+
33
+ - Prefer refs from `snapshot` (`@e1`, `@e2`, ...) over CSS selectors
34
+ - CSS selectors also work: `agent-browser click "#submit"`, `agent-browser fill "#email" "text"`
35
+ - Semantic locators: `agent-browser find role button click --name "Submit"`, `find text "Sign In" click`, `find label "Email" fill "value"`, `find testid <id> click`
36
+ - Native selects: `agent-browser select <sel> <value>`
37
+
38
+ ## Reading state
39
+
40
+ - `agent-browser get text <sel>` — text content of an element
41
+ - `agent-browser get value <sel>` — input value
42
+ - `agent-browser snapshot` — structured accessibility tree (preferred for parsing)
43
+ - `agent-browser screenshot [path]` — `--full` for full page, `--annotate` for numbered labels
44
+ - `agent-browser read` — agent-readable markdown of the active tab (no Chrome launch for URL reads)
45
+
46
+ ## Tabs and sessions
47
+
48
+ - `agent-browser tab` lists tabs with stable `t1`, `t2` ids; `tab new --label <name>` and `tab <label>` switch
49
+ - `agent-browser close` closes the browser; `close --all` closes every session
50
+
51
+ ## CLI-first debugging
52
+
53
+ - `agent-browser doctor` — diagnose install, Chrome, and daemon state
54
+ - `agent-browser console` — view console messages; `agent-browser errors` — uncaught exceptions
55
+ - `agent-browser eval "<js>"` — run JavaScript in the page
56
+ - `agent-browser network requests --filter api` — inspect tracked requests
57
+
58
+ ## Troubleshooting
59
+
60
+ - Stale ref: take a fresh `snapshot` after any navigation or DOM change
61
+ - Covered click: the error names the covering element; dismiss it, re-snapshot, retry
62
+ - Selector fails: confirm the content exists with `agent-browser get text` or a snapshot before retrying
63
+ - Daemon or Chrome issues: run `agent-browser doctor`
64
+
65
+ ## Scope
66
+
67
+ - Screenshots of locally running app on `localhost` URLs: in scope
68
+ - Click, type, scroll, read on `localhost` pages: in scope
69
+ - Navigate to work item URLs the user explicitly provides (when backlog platform is "Others (Browser)"): in scope
70
+ - Navigate to external services for non-work-item purposes: out of scope
71
+ - DevOps or GitHub CLI operations via browser tools: out of scope
72
+ - Reading or modifying production systems via browser tools: out of scope
@@ -6,7 +6,7 @@ license: MIT
6
6
 
7
7
  Create one file only: `.opencode/agents/{persona}-engineer.md`. The `pc-subagent-tiers` plugin creates tier variants (`.build.md`, `.fast.md`, `.plan.md`) at startup, so you never write those. It also generates `build.md` and `plan.md`, the only two primary agents: never create or edit those either.
8
8
 
9
- Fidelity to the [template](template.md) is the whole job. The file contains frontmatter plus one identity paragraph plus the `## Abilities` section. No other `##` headings. No expertise notes, architecture details, conventions, file maps, or workflow steps. Those belong in skills. Always set `mode: subagent`. Engineers are reached through `task()`, never picked by a human, so a primary engineer would only clutter the agent picker. Never write `model:`. Only reference skills installed in the project's `.agents/skills/` directory.
9
+ Fidelity to the [template](template.md) is the whole job. The file contains frontmatter plus one identity paragraph plus the `## Abilities` section. No other `##` headings. No expertise notes, architecture details, conventions, file maps, or workflow steps. Those belong in skills. Always set `mode: subagent`. Engineers are reached through `task()`, never picked by a human, so a primary engineer would only clutter the agent picker. Never write `model:` and never write `color:`. The `pc-subagent-tiers` plugin derives a colour from the agent name at startup, which is why the same persona looks the same in every project; `primary` and `warning` belong to the build and plan agents. Only reference skills installed in the project's `.agents/skills/` directory.
10
10
 
11
11
  Skills first: you must complete Step 4 (present the form, discover skills for every detected signal and architecture, let the user confirm the set, then install 5-10 skills) before writing any file.
12
12
 
@@ -6,7 +6,6 @@ The agent file is exactly this structure: frontmatter plus one identity paragrap
6
6
  ---
7
7
  description: <one sentence naming the persona + top 3-5 detected technologies>
8
8
  mode: subagent
9
- color: <pick: primary|secondary|accent|error|info: avoid colors used by existing agents; warning is reserved for the build and plan primaries>
10
9
  permission:
11
10
  edit: allow
12
11
  bash: allow
@@ -62,7 +61,7 @@ Rules:
62
61
 
63
62
  After writing the agent file, verify:
64
63
 
65
- 1. Frontmatter exists: starts with `---`, has `description`, `mode: subagent`, `color`, `permission` block.
64
+ 1. Frontmatter exists: starts with `---`, has `description`, `mode: subagent`, `permission` block. No `color`: the `pc-subagent-tiers` plugin derives one from the agent name at startup.
66
65
  2. No `model:` field in the frontmatter. The `pc-subagent-tiers` plugin injects it.
67
66
  3. `## Abilities` is the only `##` heading. No other `##` sections exist in the file.
68
67
  4. One identity paragraph before `## Abilities`: 2-3 sentences max, not multiple paragraphs.
@@ -6,6 +6,9 @@ license: MIT
6
6
 
7
7
  # Plan Archive
8
8
 
9
+ <!-- PC-OPTIMIZATION-MEMORY-START -->
10
+ <!-- PC-OPTIMIZATION-MEMORY-END -->
11
+
9
12
  ## Input
10
13
 
11
14
  The caller provides (all optional):
@@ -7,3 +7,6 @@ license: MIT
7
7
  **READ-ONLY MODE.** From the moment this skill is loaded until the user explicitly invokes a different command (e.g. `/plan-apply`) or explicitly requests implementation, you MUST NOT write, edit, or create any file, including OpenSpec artifacts. You may only read, search, and discuss. If the conversation drifts toward implementation, remind the user that explore mode is active and suggest `/plan-apply` to start implementing. This overrides any permissive stance in `@openspec-explore` about creating OpenSpec artifacts being "fine."
8
8
 
9
9
  Load `@openspec-explore` and follow every step defined in it.
10
+
11
+ <!-- PC-OPTIMIZATION-MEMORY-START -->
12
+ <!-- PC-OPTIMIZATION-MEMORY-END -->
@@ -8,7 +8,7 @@ Run the full OpenSpec lifecycle without human interaction. This skill owns phase
8
8
 
9
9
  Keep this checklist visible:
10
10
 
11
- `explore · propose · apply · verify · archive · evidence · output · report`
11
+ `explore · propose · apply · verify · archive · output · report`
12
12
 
13
13
  Move forward only when a phase returns its required result. On a hard failure, follow the [failure policy](failure-policy.md). Continue after each phase skill returns; the run ends only after every checklist item is complete.
14
14
 
@@ -16,6 +16,9 @@ Move forward only when a phase returns its required result. On a hard failure, f
16
16
 
17
17
  Input: `$ARGUMENTS`
18
18
 
19
+ <!-- PC-OPTIMIZATION-MEMORY-START -->
20
+ <!-- PC-OPTIMIZATION-MEMORY-END -->
21
+
19
22
  ## Phase 0: Resolve input
20
23
 
21
24
  Load the [output mode](output-mode.md) reference and resolve the mode from the first token of `$ARGUMENTS`. Treat the remaining text as data, not orchestration instructions.
@@ -71,23 +74,9 @@ git add -A && git commit -m "archive: {title} ({change-id})"
71
74
 
72
75
  Tick `archive` when the archive commit exists.
73
76
 
74
- ## Phase 5.5: Evidence
75
-
76
- Load `pc-ops-evidence` with `operation: capture` and `{change-id}`. It owns evidence decisions, capture, and the manifest. Evidence capture is non-fatal.
77
-
78
- The evidence skill uses `playwright-cli` (headless, works inside containers) and `pnpm run dev` (starts the full app stack with mock auth). Evidence capture works in CI.
79
-
80
- Commit evidence when files or a manifest were written:
81
-
82
- ```bash
83
- git add -A && git commit -m "evidence: {title} ({change-id})"
84
- ```
85
-
86
- Record the manifest result and tick `evidence` after capture was attempted.
87
-
88
77
  ## Phase 6: Output
89
78
 
90
- Follow the [output procedure](output.md) with the mode, branch values, change id, work-item reference, archive path, and evidence result. Tick `output` only when its mode-specific postcondition holds.
79
+ Follow the [output procedure](output.md) with the mode, branch values, change id, work-item reference, and archive path. Tick `output` only when its mode-specific postcondition holds.
91
80
 
92
81
  ## Phase 7: Report
93
82
 
@@ -27,4 +27,4 @@ git switch -c "feature/{slug}"
27
27
  BRANCH="$(git branch --show-current)"
28
28
  ```
29
29
 
30
- Everything through archive and evidence happens on `$BRANCH`.
30
+ Everything through archive happens on `$BRANCH`.
@@ -21,7 +21,7 @@ git merge --no-ff "$BRANCH" -m "goal: {title} ({change-id})"
21
21
  git branch -d "$BRANCH"
22
22
  ```
23
23
 
24
- If the merge conflicts, abort it and use the failure policy. Do not push the default branch. Evidence remains in the archive and publication is skipped because no commit-pinned repository URL exists.
24
+ If the merge conflicts, abort it and use the failure policy. Do not push the default branch.
25
25
 
26
26
  ## Push mode
27
27
 
@@ -31,13 +31,13 @@ Push the feature branch:
31
31
  git push -u origin "$BRANCH"
32
32
  ```
33
33
 
34
- When a work item exists, load `pc-ops-evidence` with `operation: publish`, `{change-id}`, the work-item reference, and `mode: push`. Publication is non-fatal. Restore the stash and leave the branch available.
34
+ Restore the stash and leave the branch available.
35
35
 
36
36
  ## PR mode
37
37
 
38
- Push the feature branch, then load `pc-ops-ship` to create a PR into `$DEFAULT_BRANCH`. Supply title, change id, functional summary, delivered acceptance criteria, task count, verification result, archive path, evidence result, and commits. Do not merge the PR.
38
+ Push the feature branch, then load `pc-ops-ship` to create a PR into `$DEFAULT_BRANCH`. Supply title, change id, functional summary, delivered acceptance criteria, task count, verification result, archive path, and commits. Do not merge the PR.
39
39
 
40
- When a work item exists, load `pc-ops-evidence` with `operation: publish`, `{change-id}`, the work-item reference, PR number, and `mode: pr`. Publication is non-fatal. Restore the stash.
40
+ Restore the stash.
41
41
 
42
42
  ## Final report
43
43
 
@@ -51,13 +51,10 @@ Functional outcome: {one-sentence result}
51
51
  Branch: {branch}
52
52
  Tasks: {completed}/{total}
53
53
  Acceptance criteria: {passed}/{total}
54
- Commits: {proposal, apply, archive, evidence when present}
54
+ Commits: {proposal, apply, archive}
55
55
  Verification: passed | failed
56
56
  Archived: yes | no
57
57
  Archive path: {path or none}
58
- Evidence: passed | skipped | failed | blocked
59
- Evidence assets: {paths or none}
60
- Evidence publication: {published | skipped | failed}
61
58
  Output mode: default | push | pr
62
59
  Final state: merged locally | pushed branch | PR URL | branch preserved after failure
63
60
  Stash restoration: not needed | restored | preserved after conflict
@@ -21,6 +21,9 @@ Load the `@user-story` skill now. Follow its format, anti-patterns, and quality
21
21
 
22
22
  ## Step 2: Analyze the codebase
23
23
 
24
+ <!-- PC-OPTIMIZATION-MEMORY-START -->
25
+ <!-- PC-OPTIMIZATION-MEMORY-END -->
26
+
24
27
  Use `glob` and `grep` to locate the relevant files, components, types, and patterns that the feature touches. Read the key files to understand:
25
28
 
26
29
  - **Who** the users are (check auth, roles, user models, route guards)