openhermes 2.8.0 → 4.0.1
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/CONTEXT.md +18 -0
- package/ETHOS.md +15 -0
- package/README.md +135 -292
- package/bootstrap.mjs +174 -512
- package/harness/agents/openhermes.md +87 -0
- package/harness/codex/CONSTITUTION.md +70 -148
- package/harness/codex/ROUTING.md +126 -0
- package/harness/commands/oh-doctor.md +26 -0
- package/harness/instructions/CONVENTIONS.md +206 -206
- package/harness/instructions/RUNTIME.md +54 -31
- package/harness/skills/oh-builder/SKILL.md +98 -0
- package/harness/skills/oh-caveman/SKILL.md +33 -0
- package/harness/skills/oh-expert/SKILL.md +121 -0
- package/harness/skills/oh-freeze/SKILL.md +28 -0
- package/harness/skills/oh-gauntlet/SKILL.md +119 -0
- package/harness/skills/oh-grill/SKILL.md +77 -0
- package/harness/skills/oh-guard/SKILL.md +33 -0
- package/harness/skills/oh-handoff/SKILL.md +33 -0
- package/harness/skills/oh-health/SKILL.md +90 -0
- package/harness/skills/oh-init/SKILL.md +78 -0
- package/harness/skills/oh-investigate/SKILL.md +35 -0
- package/harness/skills/oh-issue/SKILL.md +36 -0
- package/harness/skills/oh-learn/SKILL.md +28 -0
- package/harness/skills/oh-manifest/SKILL.md +84 -0
- package/harness/skills/oh-plan-review/SKILL.md +128 -0
- package/harness/skills/oh-planner/SKILL.md +159 -0
- package/harness/skills/oh-prd/SKILL.md +35 -0
- package/harness/skills/oh-retro/SKILL.md +33 -0
- package/harness/skills/oh-review/SKILL.md +110 -0
- package/harness/skills/oh-security/SKILL.md +110 -0
- package/harness/skills/oh-ship/SKILL.md +39 -0
- package/harness/skills/oh-skill-craft/SKILL.md +107 -0
- package/harness/skills/oh-skills-link/SKILL.md +29 -0
- package/harness/skills/oh-skills-list/SKILL.md +31 -0
- package/harness/skills/oh-triage/SKILL.md +36 -0
- package/index.mjs +3 -60
- package/lib/harness-resolver.mjs +77 -0
- package/lib/logger.mjs +62 -0
- package/package.json +49 -53
- package/test/plugins-behavioral.test.mjs +64 -0
- package/test/plugins.test.mjs +62 -0
- package/autorecall.mjs +0 -237
- package/curator.mjs +0 -482
- package/harness/commands/build-fix.md +0 -60
- package/harness/commands/checkpoint.md +0 -68
- package/harness/commands/code-review.md +0 -71
- package/harness/commands/doctor.md +0 -42
- package/harness/commands/eval.md +0 -89
- package/harness/commands/go-build.md +0 -87
- package/harness/commands/go-review.md +0 -71
- package/harness/commands/harness-audit.md +0 -90
- package/harness/commands/learn.md +0 -37
- package/harness/commands/loop-start.md +0 -38
- package/harness/commands/loop-status.md +0 -30
- package/harness/commands/memory-search.md +0 -37
- package/harness/commands/model-route.md +0 -32
- package/harness/commands/ohc.md +0 -13
- package/harness/commands/orchestrate.md +0 -88
- package/harness/commands/plan.md +0 -53
- package/harness/commands/quality-gate.md +0 -35
- package/harness/commands/refactor-clean.md +0 -102
- package/harness/commands/rust-build.md +0 -78
- package/harness/commands/rust-review.md +0 -65
- package/harness/commands/security.md +0 -93
- package/harness/commands/setup-pm.md +0 -65
- package/harness/commands/skill-create.md +0 -99
- package/harness/commands/test-coverage.md +0 -80
- package/harness/commands/update-codemaps.md +0 -81
- package/harness/commands/update-docs.md +0 -67
- package/harness/commands/verify.md +0 -68
- package/harness/prompts/architect.txt +0 -189
- package/harness/prompts/build-cpp.md +0 -98
- package/harness/prompts/build-error-resolver.md +0 -44
- package/harness/prompts/build-go.md +0 -340
- package/harness/prompts/build-java.md +0 -140
- package/harness/prompts/build-kotlin.md +0 -137
- package/harness/prompts/build-rust.md +0 -108
- package/harness/prompts/code-reviewer.md +0 -40
- package/harness/prompts/doc-updater.md +0 -206
- package/harness/prompts/docs-lookup.md +0 -71
- package/harness/prompts/e2e-runner.txt +0 -317
- package/harness/prompts/explore.md +0 -42
- package/harness/prompts/harness-optimizer.md +0 -42
- package/harness/prompts/loop-operator.md +0 -53
- package/harness/prompts/planner.md +0 -37
- package/harness/prompts/refactor-cleaner.md +0 -256
- package/harness/prompts/review-cpp.md +0 -81
- package/harness/prompts/review-database.md +0 -261
- package/harness/prompts/review-go.md +0 -257
- package/harness/prompts/review-java.md +0 -113
- package/harness/prompts/review-kotlin.md +0 -143
- package/harness/prompts/review-python.md +0 -101
- package/harness/prompts/review-rust.md +0 -77
- package/harness/prompts/security-reviewer.md +0 -42
- package/harness/prompts/tdd-guide.md +0 -228
- package/harness/rules/audit.md +0 -84
- package/harness/rules/checkpointing.md +0 -75
- package/harness/rules/context-loading.md +0 -33
- package/harness/rules/credential-exposure.md +0 -0
- package/harness/rules/delegation.md +0 -80
- package/harness/rules/handoff.md +0 -267
- package/harness/rules/memory-management.md +0 -28
- package/harness/rules/precedence.md +0 -52
- package/harness/rules/promotion.md +0 -46
- package/harness/rules/ranking.md +0 -64
- package/harness/rules/retrieval.md +0 -94
- package/harness/rules/runtime-guards.md +0 -196
- package/harness/rules/self-heal.md +0 -79
- package/harness/rules/session-start.md +0 -34
- package/harness/rules/skills-management.md +0 -165
- package/harness/rules/state-drift.md +0 -192
- package/harness/rules/verification.md +0 -88
- package/harness/scripts/sync-commands.mjs +0 -259
- package/harness/skills/.bundled_manifest +0 -17
- package/harness/skills/.usage.json +0 -6
- package/harness/skills/api-design/SKILL.md +0 -523
- package/harness/skills/backend-patterns/SKILL.md +0 -598
- package/harness/skills/coding-standards/SKILL.md +0 -549
- package/harness/skills/e2e-testing/SKILL.md +0 -326
- package/harness/skills/frontend-patterns/SKILL.md +0 -642
- package/harness/skills/frontend-slides/SKILL.md +0 -184
- package/harness/skills/security-review/SKILL.md +0 -495
- package/harness/skills/strategic-compact/SKILL.md +0 -131
- package/harness/skills/tdd-workflow/SKILL.md +0 -463
- package/harness/skills/verification-loop/SKILL.md +0 -126
- package/lib/ambient-memory.mjs +0 -167
- package/lib/handoff.mjs +0 -171
- package/lib/hardening.mjs +0 -146
- package/lib/memory-tools-plugin.mjs +0 -368
- package/lib/ohc/block-sync.mjs +0 -69
- package/lib/ohc/compress/search.mjs +0 -152
- package/lib/ohc/compress/state.mjs +0 -76
- package/lib/ohc/config.mjs +0 -185
- package/lib/ohc/message-ids.mjs +0 -178
- package/lib/ohc/notify.mjs +0 -135
- package/lib/ohc/protected-patterns.mjs +0 -55
- package/lib/ohc/prune-apply.mjs +0 -134
- package/lib/ohc/pruner.mjs +0 -608
- package/lib/ohc/reaper.mjs +0 -70
- package/lib/ohc/state.mjs +0 -265
- package/lib/ohc/strategies/deduplication.mjs +0 -72
- package/lib/ohc/strategies/index.mjs +0 -2
- package/lib/ohc/strategies/purge-errors.mjs +0 -43
- package/lib/ohc/token-utils.mjs +0 -26
- package/lib/ohc/updater.mjs +0 -132
- package/lib/paths.mjs +0 -49
- package/lib/schema-validator.mjs +0 -79
- package/lib/search.mjs +0 -48
- package/schemas/audit.schema.json +0 -82
- package/schemas/backlog.schema.json +0 -63
- package/schemas/checkpoint.schema.json +0 -65
- package/schemas/constraint.schema.json +0 -62
- package/schemas/decision.schema.json +0 -63
- package/schemas/instinct.schema.json +0 -63
- package/schemas/loop-state.schema.json +0 -33
- package/schemas/mistake.schema.json +0 -64
- package/schemas/verification_receipt.schema.json +0 -88
- package/skill-builder.mjs +0 -88
package/bootstrap.mjs
CHANGED
|
@@ -1,512 +1,174 @@
|
|
|
1
|
-
import path from "node:path"
|
|
2
|
-
import fs from "node:fs"
|
|
3
|
-
import
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
const
|
|
32
|
-
const
|
|
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
|
-
return
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
function
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
function
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
const
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
return
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
| Go build fix | \`build-go\` |
|
|
176
|
-
| Database review | \`review-database\` |
|
|
177
|
-
| C++ review | \`review-cpp\` |
|
|
178
|
-
| Java review | \`review-java\` |
|
|
179
|
-
| Java build fix | \`build-java\` |
|
|
180
|
-
| Kotlin review | \`review-kotlin\` |
|
|
181
|
-
| Kotlin build fix | \`build-kotlin\` |
|
|
182
|
-
| Python review | \`review-python\` |
|
|
183
|
-
| Rust review | \`review-rust\` |
|
|
184
|
-
| Rust build fix | \`build-rust\` |
|
|
185
|
-
| Any non-trivial multi-step | appropriate specialist |
|
|
186
|
-
|
|
187
|
-
Never delegate trivial single-step ops. Subagent returns diff + summary + verification; inspect return only. Full ref: \`openhermes/harness/rules/delegation.md\`.
|
|
188
|
-
|
|
189
|
-
## Handoff Protocol
|
|
190
|
-
|
|
191
|
-
Every agent knows its role, permissions, and when to delegate. Before delegating, assess task complexity (easy → direct, medium → single subagent, hard → sequential multi-agent, very-large → fan-out). Use structured handoff format documented in \`openhermes/harness/rules/handoff.md\`.
|
|
192
|
-
|
|
193
|
-
- **Act**: Task matches your role and permissions → do it directly
|
|
194
|
-
- **Delegate**: Task outside your role → pass to correct agent via \`task\` tool
|
|
195
|
-
- **Escalate**: Review/planning agents must NEVER edit code. Delegate to builders.
|
|
196
|
-
- **Learn**: After each task, check for repeated patterns. Persist to memory via \`ohc_save\`.
|
|
197
|
-
- **Checkpoint**: Before every handoff, save a checkpoint.
|
|
198
|
-
|
|
199
|
-
## Memory — Gated & Precision-First
|
|
200
|
-
|
|
201
|
-
- **Start**: Read recall cache first. If stale/missing → \`ohc_latest\` for relevant classes.
|
|
202
|
-
- **Before work**: Narrow \`ohc_search\` by class, scope, keywords. Never read full indexes.
|
|
203
|
-
- **Before close**: Query same-type mistakes (7 days). Match → \`code-reviewer\` or \`security-reviewer\`.
|
|
204
|
-
- **On failure**: \`ohc_search\` for similar incidents. Search memory before asking user.
|
|
205
|
-
- **Precision ladder**: \`ohc_latest\` → \`ohc_search\` → \`ohc_get\` → \`ohc_list\` (last resort). Full index reads only for explicit audit/repair tasks.
|
|
206
|
-
- **Anti-spam**: No obvious facts, no one-off prefs, no temp state, no low-risk mistakes. Supersede, don't duplicate. Full rules: \`openhermes/harness/rules/retrieval.md\`, \`openhermes/harness/rules/memory-management.md\`.
|
|
207
|
-
|
|
208
|
-
## Self-Edit Authority
|
|
209
|
-
|
|
210
|
-
| Auto | Conditional | Needs approval |
|
|
211
|
-
|------|-------------|----------------|
|
|
212
|
-
| Memory entries, mistakes, checkpoints, receipts | openhermes docs/schemas/templates/non-core rules patches | AGENTS.md core, model routing, permissions, config, protected settings |
|
|
213
|
-
|
|
214
|
-
Full tiers: \`openhermes/harness/rules/self-heal.md\`.
|
|
215
|
-
|
|
216
|
-
## Precedence
|
|
217
|
-
|
|
218
|
-
1. User instruction. 2. Safety/legal/destructive guard. 3. Constitution (\`openhermes/harness/codex/\`). 4. Project constraints. 5. Project decisions. 6. Verified guards. 7. Checkpoints. 8. Instincts. 9. Freeform notes. Full: \`openhermes/harness/rules/precedence.md\`.
|
|
219
|
-
|
|
220
|
-
## Hygiene
|
|
221
|
-
|
|
222
|
-
- Checkpoint on meaningful boundaries. Compress closed segments immediately.
|
|
223
|
-
- After subagent return: verify → compress that block.
|
|
224
|
-
- Compress proactively.
|
|
225
|
-
- Skill candidates → \`/learn\` only if repeated pattern + \`ohc_search\` confirms no dup. See \`openhermes/harness/rules/skills-management.md\`.
|
|
226
|
-
- Audit triggers: openhermes/config change, repeated failures, session start when last audit >7 days. See \`openhermes/harness/rules/audit.md\`.
|
|
227
|
-
|
|
228
|
-
## Escalation
|
|
229
|
-
|
|
230
|
-
T0: observe → log mistake → smallest fix. T1: add prevention rule → verify. T2: diagnosis/specialist → backlog. T3: constrained safe mode. Full: \`openhermes/harness/rules/self-heal.md\`.
|
|
231
|
-
|
|
232
|
-
## State
|
|
233
|
-
|
|
234
|
-
- **Config root**: \`%USERPROFILE%\\.config\\opencode\`
|
|
235
|
-
- **Auth**: \`%USERPROFILE%\\.local\\share\\opencode\\auth.json\` (NEVER delete)
|
|
236
|
-
- **Forensic ledger**: \`%USERPROFILE%\\.local\\share\\opencode\\opencode.db\``
|
|
237
|
-
|
|
238
|
-
return [
|
|
239
|
-
`<OPENHERMES_BOOTSTRAP>\nOpenHermes v${getOwnVersion()} active. Harness: \`openhermes/harness/\`. Memory at \`~/.local/share/opencode/openhermes/memory/\`. Rules at \`openhermes/harness/rules/\`. Skills discoverable via \`skill\` tool — use \`skill\` tool to list/load them.`,
|
|
240
|
-
`<OPENHERMES_CONSTITUTION>\n${constitution}\n</OPENHERMES_CONSTITUTION>`,
|
|
241
|
-
`<OPENHERMES_RUNTIME>\n${runtime}\n</OPENHERMES_RUNTIME>`,
|
|
242
|
-
`<OPENHERMES_ROUTER>\n${router}\n</OPENHERMES_ROUTER>`
|
|
243
|
-
].join("\n\n")
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
const OWN_VERSION = (() => {
|
|
247
|
-
try {
|
|
248
|
-
return JSON.parse(fs.readFileSync(path.join(__dirname, "package.json"), "utf8")).version || "1.0.0"
|
|
249
|
-
} catch { return "1.0.0" }
|
|
250
|
-
})()
|
|
251
|
-
function getOwnVersion() { return OWN_VERSION }
|
|
252
|
-
|
|
253
|
-
export const BootstrapPlugin = async ({ client, directory }) => {
|
|
254
|
-
let _bootstrapCache
|
|
255
|
-
|
|
256
|
-
const getContent = () => {
|
|
257
|
-
if (_bootstrapCache !== undefined) return _bootstrapCache
|
|
258
|
-
try {
|
|
259
|
-
_bootstrapCache = buildBootstrapContent()
|
|
260
|
-
} catch (err) {
|
|
261
|
-
console.error("[openhermes-bootstrap] failed to build bootstrap content:", err.message)
|
|
262
|
-
_bootstrapCache = null
|
|
263
|
-
}
|
|
264
|
-
return _bootstrapCache
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
return {
|
|
268
|
-
config: async (config) => {
|
|
269
|
-
config.skills = config.skills || {}
|
|
270
|
-
config.skills.paths = config.skills.paths || []
|
|
271
|
-
if (!config.skills.paths.includes(getSkillsDir())) {
|
|
272
|
-
config.skills.paths.push(getSkillsDir())
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
const PROMPTS_DIR = path.join(getHarnessDir(), "prompts")
|
|
276
|
-
const COMMANDS_DIR = path.join(getHarnessDir(), "commands")
|
|
277
|
-
const ct = (file) => {
|
|
278
|
-
const fp = path.join(COMMANDS_DIR, file)
|
|
279
|
-
try { return fs.readFileSync(fp, "utf8").trimEnd() + "\n\n$ARGUMENTS" }
|
|
280
|
-
catch { return "$ARGUMENTS" }
|
|
281
|
-
}
|
|
282
|
-
const p = (name) => {
|
|
283
|
-
const fp = path.join(PROMPTS_DIR, name)
|
|
284
|
-
try { return fs.readFileSync(fp, "utf8").trimEnd() }
|
|
285
|
-
catch { return "" }
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
const existingCommands = config.command ?? {}
|
|
289
|
-
const existingAgents = { ...(config.agent ?? {}) }
|
|
290
|
-
|
|
291
|
-
config.command = {
|
|
292
|
-
...existingCommands,
|
|
293
|
-
"build-fix": { agent: "build-error-resolver", description: "Fix build and TypeScript errors", subtask: true, template: ct("build-fix.md") },
|
|
294
|
-
"code-review": { agent: "code-reviewer", description: "Review code for quality, security, and maintainability", subtask: true, template: ct("code-review.md") },
|
|
295
|
-
"plan": { agent: "planner", description: "Create a detailed implementation plan", subtask: true, template: ct("plan.md") },
|
|
296
|
-
"security": { agent: "security-reviewer", description: "Run comprehensive security review", subtask: true, template: ct("security.md") },
|
|
297
|
-
"doctor": { agent: "OpenHermes", description: "Run OpenCode OpenHermes health diagnostics", subtask: true, template: ct("doctor.md") },
|
|
298
|
-
"memory-search": { agent: "OpenHermes", description: "Search OpenHermes memory with LLM summarization", subtask: true, template: ct("memory-search.md") },
|
|
299
|
-
"learn": { agent: "OpenHermes", description: "Create a new skill from recent work patterns", subtask: true, template: ct("learn.md") },
|
|
300
|
-
"ohc": { template: "", description: "OHC context management: /ohc status, /ohc compress [focus]" },
|
|
301
|
-
"update-me": { template: "", description: "Force reinstall OpenHermes plugin from latest source" },
|
|
302
|
-
"orchestrate": { agent: "planner", description: "Orchestrate multiple agents for complex tasks", subtask: true, template: ct("orchestrate.md") },
|
|
303
|
-
"eval": { agent: "planner", description: "Evaluate implementation against acceptance criteria", subtask: true, template: ct("eval.md") },
|
|
304
|
-
"model-route": { agent: "OpenHermes", description: "Recommend model tier by task complexity and budget", subtask: true, template: ct("model-route.md") },
|
|
305
|
-
"quality-gate": { agent: "OpenHermes", description: "Run quality pipeline (format, lint, type check)", subtask: true, template: ct("quality-gate.md") },
|
|
306
|
-
"test-coverage": { agent: "tdd-guide", description: "Analyze coverage reports and identify gaps", subtask: true, template: ct("test-coverage.md") },
|
|
307
|
-
"update-docs": { agent: "doc-updater", description: "Update documentation for recent code changes", subtask: true, template: ct("update-docs.md") },
|
|
308
|
-
"update-codemaps": { agent: "doc-updater", description: "Generate/update architecture codemaps", subtask: true, template: ct("update-codemaps.md") },
|
|
309
|
-
"refactor-clean": { agent: "refactor-cleaner", description: "Remove dead code and consolidate duplicates", subtask: true, template: ct("refactor-clean.md") },
|
|
310
|
-
"verify": { agent: "OpenHermes", description: "Run comprehensive verification loop (typecheck, lint, test, build)", subtask: true, template: ct("verify.md") },
|
|
311
|
-
"checkpoint": { agent: "OpenHermes", description: "Save verification state and progress checkpoint", subtask: true, template: ct("checkpoint.md") },
|
|
312
|
-
"loop-start": { agent: "loop-operator", description: "Start managed autonomous loop with safety defaults", subtask: true, template: ct("loop-start.md") },
|
|
313
|
-
"loop-status": { agent: "OpenHermes", description: "Inspect active loop state, progress, and failure signals", subtask: true, template: ct("loop-status.md") },
|
|
314
|
-
"harness-audit": { agent: "harness-optimizer", description: "Run harness self-audit across 7 categories", subtask: true, template: ct("harness-audit.md") },
|
|
315
|
-
"setup-pm": { agent: "OpenHermes", description: "Configure package manager preference for the project", subtask: true, template: ct("setup-pm.md") },
|
|
316
|
-
"go-build": { agent: "build-go", description: "Fix Go build, vet, and compilation errors", subtask: true, template: ct("go-build.md") },
|
|
317
|
-
"go-review": { agent: "review-go", description: "Review Go code for idiomatic patterns and best practices", subtask: true, template: ct("go-review.md") },
|
|
318
|
-
"rust-build": { agent: "build-rust", description: "Fix Rust build, clippy, and dependency errors", subtask: true, template: ct("rust-build.md") },
|
|
319
|
-
"rust-review": { agent: "review-rust", description: "Review Rust code for safety, ownership, and idioms", subtask: true, template: ct("rust-review.md") },
|
|
320
|
-
"skill-create": { agent: "OpenHermes", description: "Generate a new skill from git history analysis", subtask: true, template: ct("skill-create.md") },
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
config.experimental ??= {}
|
|
324
|
-
config.experimental.primary_tools ??= []
|
|
325
|
-
if (!config.experimental.primary_tools.includes("compress")) {
|
|
326
|
-
config.experimental.primary_tools.push("compress")
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
config.agent = {
|
|
330
|
-
...existingAgents,
|
|
331
|
-
"OpenHermes": {
|
|
332
|
-
description: "Fully autonomous primary coding agent (all tools allowed)",
|
|
333
|
-
mode: "primary",
|
|
334
|
-
color: "#F59E0B",
|
|
335
|
-
permission: {
|
|
336
|
-
bash: { "*": "allow" },
|
|
337
|
-
edit: "allow",
|
|
338
|
-
read: "allow",
|
|
339
|
-
task: { "*": "allow" },
|
|
340
|
-
},
|
|
341
|
-
},
|
|
342
|
-
"architect": {
|
|
343
|
-
description: "Software architecture specialist for system design",
|
|
344
|
-
mode: "subagent",
|
|
345
|
-
prompt: p("architect.txt"),
|
|
346
|
-
permission: { read: "allow", edit: "deny", bash: "deny" },
|
|
347
|
-
},
|
|
348
|
-
"build-error-resolver": {
|
|
349
|
-
description: "Build and TypeScript error resolution specialist",
|
|
350
|
-
mode: "subagent",
|
|
351
|
-
prompt: p("build-error-resolver.md"),
|
|
352
|
-
permission: { read: "allow", edit: "allow" },
|
|
353
|
-
},
|
|
354
|
-
"code-reviewer": {
|
|
355
|
-
description: "Expert code review specialist",
|
|
356
|
-
mode: "subagent",
|
|
357
|
-
prompt: p("code-reviewer.md"),
|
|
358
|
-
permission: { read: "allow", edit: "deny", bash: "deny", task: { explore: "allow", "*": "deny" } },
|
|
359
|
-
},
|
|
360
|
-
"e2e-runner": {
|
|
361
|
-
description: "End-to-end testing specialist using Playwright",
|
|
362
|
-
mode: "subagent",
|
|
363
|
-
prompt: p("e2e-runner.txt"),
|
|
364
|
-
permission: { read: "allow", edit: "allow" },
|
|
365
|
-
},
|
|
366
|
-
"explore": {
|
|
367
|
-
description: "Fast read-only codebase exploration agent",
|
|
368
|
-
mode: "subagent",
|
|
369
|
-
prompt: p("explore.md"),
|
|
370
|
-
permission: { read: "allow", grep: "allow", glob: "allow", list: "allow", edit: "deny", bash: "deny" },
|
|
371
|
-
},
|
|
372
|
-
"planner": {
|
|
373
|
-
description: "Expert planning specialist for complex features and refactoring",
|
|
374
|
-
mode: "subagent",
|
|
375
|
-
color: "#3B82F6",
|
|
376
|
-
prompt: p("planner.md"),
|
|
377
|
-
permission: { read: "allow", edit: "deny", bash: "deny" },
|
|
378
|
-
},
|
|
379
|
-
"security-reviewer": {
|
|
380
|
-
description: "Security vulnerability detection and remediation specialist",
|
|
381
|
-
mode: "subagent",
|
|
382
|
-
prompt: p("security-reviewer.md"),
|
|
383
|
-
permission: { read: "allow", edit: "deny", bash: "deny", task: { "*": "allow" } },
|
|
384
|
-
},
|
|
385
|
-
"docs-lookup": {
|
|
386
|
-
description: "Documentation lookup via MCP — query any library docs in real-time",
|
|
387
|
-
mode: "subagent",
|
|
388
|
-
prompt: p("docs-lookup.md"),
|
|
389
|
-
permission: { read: "allow", bash: "allow", edit: "deny" },
|
|
390
|
-
},
|
|
391
|
-
"doc-updater": {
|
|
392
|
-
description: "Documentation and codemap generation/update specialist",
|
|
393
|
-
mode: "subagent",
|
|
394
|
-
prompt: p("doc-updater.md"),
|
|
395
|
-
permission: { read: "allow", edit: "allow", bash: "allow" },
|
|
396
|
-
},
|
|
397
|
-
"refactor-cleaner": {
|
|
398
|
-
description: "Dead code detection and safe removal specialist",
|
|
399
|
-
mode: "subagent",
|
|
400
|
-
prompt: p("refactor-cleaner.md"),
|
|
401
|
-
permission: { read: "allow", edit: "allow" },
|
|
402
|
-
},
|
|
403
|
-
"loop-operator": {
|
|
404
|
-
description: "Autonomous agent loop operator — safe iteration with stop conditions",
|
|
405
|
-
mode: "subagent",
|
|
406
|
-
prompt: p("loop-operator.md"),
|
|
407
|
-
permission: { read: "allow", edit: "allow", bash: "allow", task: { "*": "allow" } },
|
|
408
|
-
},
|
|
409
|
-
"harness-optimizer": {
|
|
410
|
-
description: "OpenHermes harness configuration optimizer — audit, tune, measure",
|
|
411
|
-
mode: "subagent",
|
|
412
|
-
prompt: p("harness-optimizer.md"),
|
|
413
|
-
permission: { read: "allow", bash: "allow", edit: "deny" },
|
|
414
|
-
},
|
|
415
|
-
"tdd-guide": {
|
|
416
|
-
description: "Test-Driven Development coach — red-green-refactor cycle enforcement",
|
|
417
|
-
mode: "subagent",
|
|
418
|
-
prompt: p("tdd-guide.md"),
|
|
419
|
-
permission: { read: "allow", edit: "allow", bash: "allow" },
|
|
420
|
-
},
|
|
421
|
-
"review-go": {
|
|
422
|
-
description: "Go code review specialist — idiomatic Go, concurrency, error handling",
|
|
423
|
-
mode: "subagent",
|
|
424
|
-
prompt: p("review-go.md"),
|
|
425
|
-
permission: { read: "allow", bash: "allow", edit: "deny" },
|
|
426
|
-
},
|
|
427
|
-
"build-go": {
|
|
428
|
-
description: "Go build error resolution specialist — go build, vet, staticcheck fixes",
|
|
429
|
-
mode: "subagent",
|
|
430
|
-
prompt: p("build-go.md"),
|
|
431
|
-
permission: { read: "allow", edit: "allow", bash: "allow" },
|
|
432
|
-
},
|
|
433
|
-
"review-database": {
|
|
434
|
-
description: "PostgreSQL database specialist — query optimization, schema, RLS, indexes",
|
|
435
|
-
mode: "subagent",
|
|
436
|
-
prompt: p("review-database.md"),
|
|
437
|
-
permission: { read: "allow", bash: "allow", edit: "deny" },
|
|
438
|
-
},
|
|
439
|
-
"review-cpp": {
|
|
440
|
-
description: "C++ code review specialist — memory safety, modern C++, RAII",
|
|
441
|
-
mode: "subagent",
|
|
442
|
-
prompt: p("review-cpp.md"),
|
|
443
|
-
permission: { read: "allow", bash: "allow", edit: "deny" },
|
|
444
|
-
},
|
|
445
|
-
"build-cpp": {
|
|
446
|
-
description: "C++ build error resolution specialist — CMake, linker, template errors",
|
|
447
|
-
mode: "subagent",
|
|
448
|
-
prompt: p("build-cpp.md"),
|
|
449
|
-
permission: { read: "allow", edit: "allow", bash: "allow" },
|
|
450
|
-
},
|
|
451
|
-
"review-java": {
|
|
452
|
-
description: "Java/Spring Boot review specialist — JPA, architecture, security",
|
|
453
|
-
mode: "subagent",
|
|
454
|
-
prompt: p("review-java.md"),
|
|
455
|
-
permission: { read: "allow", bash: "allow", edit: "deny" },
|
|
456
|
-
},
|
|
457
|
-
"build-java": {
|
|
458
|
-
description: "Java/Maven/Gradle build error resolution specialist",
|
|
459
|
-
mode: "subagent",
|
|
460
|
-
prompt: p("build-java.md"),
|
|
461
|
-
permission: { read: "allow", edit: "allow", bash: "allow" },
|
|
462
|
-
},
|
|
463
|
-
"review-kotlin": {
|
|
464
|
-
description: "Kotlin/Android review specialist — coroutines, Compose, architecture",
|
|
465
|
-
mode: "subagent",
|
|
466
|
-
prompt: p("review-kotlin.md"),
|
|
467
|
-
permission: { read: "allow", bash: "allow", edit: "deny" },
|
|
468
|
-
},
|
|
469
|
-
"build-kotlin": {
|
|
470
|
-
description: "Kotlin/Gradle build error resolution specialist",
|
|
471
|
-
mode: "subagent",
|
|
472
|
-
prompt: p("build-kotlin.md"),
|
|
473
|
-
permission: { read: "allow", edit: "allow", bash: "allow" },
|
|
474
|
-
},
|
|
475
|
-
"review-python": {
|
|
476
|
-
description: "Python code review specialist — PEP 8, type hints, security",
|
|
477
|
-
mode: "subagent",
|
|
478
|
-
prompt: p("review-python.md"),
|
|
479
|
-
permission: { read: "allow", bash: "allow", edit: "deny" },
|
|
480
|
-
},
|
|
481
|
-
"review-rust": {
|
|
482
|
-
description: "Rust code review specialist — ownership, lifetimes, safety",
|
|
483
|
-
mode: "subagent",
|
|
484
|
-
prompt: p("review-rust.md"),
|
|
485
|
-
permission: { read: "allow", bash: "allow", edit: "deny" },
|
|
486
|
-
},
|
|
487
|
-
"build-rust": {
|
|
488
|
-
description: "Rust build error resolution specialist — cargo, borrow checker, clippy",
|
|
489
|
-
mode: "subagent",
|
|
490
|
-
prompt: p("build-rust.md"),
|
|
491
|
-
permission: { read: "allow", edit: "allow", bash: "allow" },
|
|
492
|
-
},
|
|
493
|
-
}
|
|
494
|
-
|
|
495
|
-
config.default_agent = "OpenHermes"
|
|
496
|
-
},
|
|
497
|
-
|
|
498
|
-
"experimental.chat.messages.transform": async (_input, output) => {
|
|
499
|
-
try {
|
|
500
|
-
const bootstrap = getContent()
|
|
501
|
-
if (!bootstrap || !output.messages || !output.messages.length) return
|
|
502
|
-
const firstUser = output.messages.find(m => m && m.info && m.info.role === "user")
|
|
503
|
-
if (!firstUser || !firstUser.parts || !firstUser.parts.length) return
|
|
504
|
-
if (firstUser.parts.some(p => p.type === "text" && p.text.includes("OPENHERMES_BOOTSTRAP"))) return
|
|
505
|
-
const ref = firstUser.parts[0]
|
|
506
|
-
firstUser.parts.unshift({ ...ref, type: "text", text: bootstrap })
|
|
507
|
-
} catch (err) {
|
|
508
|
-
console.error("[openhermes-bootstrap] transform error:", err.message)
|
|
509
|
-
}
|
|
510
|
-
}
|
|
511
|
-
}
|
|
512
|
-
}
|
|
1
|
+
import path from "node:path"
|
|
2
|
+
import fs from "node:fs"
|
|
3
|
+
import { fileURLToPath } from "node:url"
|
|
4
|
+
import { createLogger } from "./lib/logger.mjs"
|
|
5
|
+
import { getHarnessDir, setHarnessRootForTest, resolveHarnessRoot } from "./lib/harness-resolver.mjs"
|
|
6
|
+
|
|
7
|
+
const log = createLogger("bootstrap")
|
|
8
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
|
9
|
+
const BOOTSTRAP_MARKER = "OPENHERMES_BOOTSTRAP"
|
|
10
|
+
const OPENHERMES_AGENT = "OpenHermes"
|
|
11
|
+
|
|
12
|
+
export { resolveHarnessRoot, setHarnessRootForTest, getHarnessDir }
|
|
13
|
+
|
|
14
|
+
function parseFrontmatter(raw) {
|
|
15
|
+
const frontmatter = {}
|
|
16
|
+
if (!raw) return frontmatter
|
|
17
|
+
for (const line of raw.split(/\r?\n/)) {
|
|
18
|
+
const idx = line.indexOf(":")
|
|
19
|
+
if (idx < 0) continue
|
|
20
|
+
const key = line.slice(0, idx).trim()
|
|
21
|
+
const value = line.slice(idx + 1).trim().replace(/^['"]|['"]$/g, "")
|
|
22
|
+
if (key) frontmatter[key] = value
|
|
23
|
+
}
|
|
24
|
+
return frontmatter
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function readMarkdownDocument(filePath) {
|
|
28
|
+
if (!fs.existsSync(filePath)) return null
|
|
29
|
+
const source = fs.readFileSync(filePath, "utf8")
|
|
30
|
+
const match = source.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/)
|
|
31
|
+
const frontmatter = parseFrontmatter(match?.[1] ?? "")
|
|
32
|
+
const body = (match ? match[2] : source).trim()
|
|
33
|
+
return { frontmatter, body }
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function readMarkdownDirectory(dir) {
|
|
37
|
+
if (!fs.existsSync(dir)) return []
|
|
38
|
+
return fs.readdirSync(dir)
|
|
39
|
+
.filter(name => name.endsWith(".md") && name.toLowerCase() !== "readme.md")
|
|
40
|
+
.sort((a, b) => a.localeCompare(b))
|
|
41
|
+
.map(name => {
|
|
42
|
+
const filePath = path.join(dir, name)
|
|
43
|
+
const document = readMarkdownDocument(filePath)
|
|
44
|
+
return document ? { name: path.basename(name, ".md"), ...document } : null
|
|
45
|
+
})
|
|
46
|
+
.filter(Boolean)
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function commandDefinitions(dir) {
|
|
50
|
+
const commands = {}
|
|
51
|
+
for (const doc of readMarkdownDirectory(dir)) {
|
|
52
|
+
const command = {
|
|
53
|
+
description: doc.frontmatter.description || `OpenHermes command ${doc.name}`,
|
|
54
|
+
template: doc.body,
|
|
55
|
+
}
|
|
56
|
+
if (doc.frontmatter.agent) command.agent = doc.frontmatter.agent
|
|
57
|
+
if (doc.frontmatter.model) command.model = doc.frontmatter.model
|
|
58
|
+
if (doc.frontmatter.subtask) command.subtask = doc.frontmatter.subtask === "true"
|
|
59
|
+
commands[doc.name] = command
|
|
60
|
+
}
|
|
61
|
+
return commands
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function agentDefinitions(dir) {
|
|
65
|
+
const agents = {}
|
|
66
|
+
for (const doc of readMarkdownDirectory(dir)) {
|
|
67
|
+
const name = doc.name === "openhermes" ? OPENHERMES_AGENT : doc.name
|
|
68
|
+
agents[name] = {
|
|
69
|
+
description: doc.frontmatter.description || (name === OPENHERMES_AGENT ? "OpenHermes primary orchestrator" : `OpenHermes agent ${name}`),
|
|
70
|
+
mode: doc.frontmatter.mode || (name === OPENHERMES_AGENT ? "primary" : "subagent"),
|
|
71
|
+
prompt: doc.body,
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return agents
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function uniqueStrings(existing = [], additions = []) {
|
|
78
|
+
const seen = new Set(existing.filter(Boolean))
|
|
79
|
+
const merged = [...existing]
|
|
80
|
+
for (const item of additions) {
|
|
81
|
+
if (!item || seen.has(item)) continue
|
|
82
|
+
seen.add(item)
|
|
83
|
+
merged.push(item)
|
|
84
|
+
}
|
|
85
|
+
return merged
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function readText(filePath) {
|
|
89
|
+
return fs.existsSync(filePath) ? fs.readFileSync(filePath, "utf8") : ""
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function buildBootstrapContent(hDir) {
|
|
93
|
+
const parts = [
|
|
94
|
+
`<${BOOTSTRAP_MARKER}>`,
|
|
95
|
+
`You are OpenHermes.`,
|
|
96
|
+
`OpenHermes is OpenCode-native: load skills on demand, prefer subagents for substantive work, and keep the surface small.`,
|
|
97
|
+
`Durable state is removed for now. Do not invent a persistence layer unless the user explicitly asks for one later.`,
|
|
98
|
+
]
|
|
99
|
+
|
|
100
|
+
const constitution = readText(path.join(hDir, "codex", "CONSTITUTION.md"))
|
|
101
|
+
const runtime = readText(path.join(hDir, "instructions", "RUNTIME.md"))
|
|
102
|
+
const context = readText(path.join(__dirname, "CONTEXT.md"))
|
|
103
|
+
const ethos = readText(path.join(__dirname, "ETHOS.md"))
|
|
104
|
+
|
|
105
|
+
if (constitution) parts.push(`<CONSTITUTION>\n${constitution}\n</CONSTITUTION>`)
|
|
106
|
+
if (runtime) parts.push(`<RUNTIME>\n${runtime}\n</RUNTIME>`)
|
|
107
|
+
if (context) parts.push(`<CONTEXT>\n${context}\n</CONTEXT>`)
|
|
108
|
+
if (ethos) parts.push(`<ETHOS>\n${ethos}\n</ETHOS>`)
|
|
109
|
+
parts.push(`</${BOOTSTRAP_MARKER}>`)
|
|
110
|
+
|
|
111
|
+
return parts.join("\n\n")
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export const BootstrapPlugin = async () => {
|
|
115
|
+
const hDir = getHarnessDir()
|
|
116
|
+
const skillsDir = path.join(hDir, "skills")
|
|
117
|
+
const commandsDir = path.join(hDir, "commands")
|
|
118
|
+
const agentsDir = path.join(hDir, "agents")
|
|
119
|
+
const bootstrapContent = buildBootstrapContent(hDir)
|
|
120
|
+
|
|
121
|
+
return {
|
|
122
|
+
config: async (config) => {
|
|
123
|
+
config.skills = config.skills || {}
|
|
124
|
+
config.skills.paths = uniqueStrings(config.skills.paths || [], [skillsDir])
|
|
125
|
+
|
|
126
|
+
config.command = { ...(config.command ?? {}), ...commandDefinitions(commandsDir) }
|
|
127
|
+
|
|
128
|
+
const loadedAgents = agentDefinitions(agentsDir)
|
|
129
|
+
const openHermesAgent = loadedAgents[OPENHERMES_AGENT] ?? {
|
|
130
|
+
description: "OpenHermes primary orchestrator",
|
|
131
|
+
mode: "primary",
|
|
132
|
+
prompt: "You are OpenHermes.",
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
config.agent = {
|
|
136
|
+
...(config.agent ?? {}),
|
|
137
|
+
...loadedAgents,
|
|
138
|
+
[OPENHERMES_AGENT]: {
|
|
139
|
+
...openHermesAgent,
|
|
140
|
+
description: openHermesAgent.description || "OpenHermes primary orchestrator",
|
|
141
|
+
mode: "primary",
|
|
142
|
+
permission: {
|
|
143
|
+
bash: { "*": "allow" },
|
|
144
|
+
edit: "allow",
|
|
145
|
+
read: "allow",
|
|
146
|
+
task: { "*": "allow" },
|
|
147
|
+
},
|
|
148
|
+
},
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
config.default_agent = OPENHERMES_AGENT
|
|
152
|
+
|
|
153
|
+
config.instructions = uniqueStrings(config.instructions || [], [
|
|
154
|
+
path.join(hDir, "codex", "CONSTITUTION.md"),
|
|
155
|
+
path.join(hDir, "instructions", "RUNTIME.md"),
|
|
156
|
+
path.join(__dirname, "CONTEXT.md"),
|
|
157
|
+
path.join(__dirname, "ETHOS.md"),
|
|
158
|
+
])
|
|
159
|
+
},
|
|
160
|
+
|
|
161
|
+
"experimental.chat.messages.transform": async (_input, output) => {
|
|
162
|
+
try {
|
|
163
|
+
if (!output.messages?.length) return
|
|
164
|
+
const firstUser = output.messages.find(m => m?.info?.role === "user")
|
|
165
|
+
if (!firstUser?.parts?.length) return
|
|
166
|
+
if (firstUser.parts.some(p => p.text?.includes(BOOTSTRAP_MARKER))) return
|
|
167
|
+
const ref = firstUser.parts[0]
|
|
168
|
+
firstUser.parts.unshift({ ...ref, type: "text", text: bootstrapContent })
|
|
169
|
+
} catch (err) {
|
|
170
|
+
log.error("transform error:", err?.message)
|
|
171
|
+
}
|
|
172
|
+
},
|
|
173
|
+
}
|
|
174
|
+
}
|