openhermes 2.8.0 → 4.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.
Files changed (158) hide show
  1. package/CONTEXT.md +18 -0
  2. package/ETHOS.md +15 -0
  3. package/README.md +135 -292
  4. package/bootstrap.mjs +174 -512
  5. package/harness/agents/openhermes.md +87 -0
  6. package/harness/codex/CONSTITUTION.md +70 -148
  7. package/harness/codex/ROUTING.md +126 -0
  8. package/harness/commands/oh-doctor.md +26 -0
  9. package/harness/instructions/CONVENTIONS.md +206 -206
  10. package/harness/instructions/RUNTIME.md +54 -31
  11. package/harness/skills/oh-builder/SKILL.md +98 -0
  12. package/harness/skills/oh-caveman/SKILL.md +33 -0
  13. package/harness/skills/oh-expert/SKILL.md +121 -0
  14. package/harness/skills/oh-freeze/SKILL.md +28 -0
  15. package/harness/skills/oh-gauntlet/SKILL.md +119 -0
  16. package/harness/skills/oh-grill/SKILL.md +77 -0
  17. package/harness/skills/oh-guard/SKILL.md +33 -0
  18. package/harness/skills/oh-handoff/SKILL.md +33 -0
  19. package/harness/skills/oh-health/SKILL.md +90 -0
  20. package/harness/skills/oh-init/SKILL.md +78 -0
  21. package/harness/skills/oh-investigate/SKILL.md +35 -0
  22. package/harness/skills/oh-issue/SKILL.md +36 -0
  23. package/harness/skills/oh-learn/SKILL.md +28 -0
  24. package/harness/skills/oh-manifest/SKILL.md +84 -0
  25. package/harness/skills/oh-plan-review/SKILL.md +128 -0
  26. package/harness/skills/oh-planner/SKILL.md +157 -0
  27. package/harness/skills/oh-prd/SKILL.md +35 -0
  28. package/harness/skills/oh-retro/SKILL.md +33 -0
  29. package/harness/skills/oh-review/SKILL.md +110 -0
  30. package/harness/skills/oh-security/SKILL.md +110 -0
  31. package/harness/skills/oh-ship/SKILL.md +39 -0
  32. package/harness/skills/oh-skill-craft/SKILL.md +107 -0
  33. package/harness/skills/oh-skills-link/SKILL.md +29 -0
  34. package/harness/skills/oh-skills-list/SKILL.md +31 -0
  35. package/harness/skills/oh-triage/SKILL.md +36 -0
  36. package/index.mjs +3 -60
  37. package/lib/harness-resolver.mjs +77 -0
  38. package/lib/logger.mjs +62 -0
  39. package/package.json +49 -53
  40. package/test/plugins-behavioral.test.mjs +64 -0
  41. package/test/plugins.test.mjs +62 -0
  42. package/autorecall.mjs +0 -237
  43. package/curator.mjs +0 -482
  44. package/harness/commands/build-fix.md +0 -60
  45. package/harness/commands/checkpoint.md +0 -68
  46. package/harness/commands/code-review.md +0 -71
  47. package/harness/commands/doctor.md +0 -42
  48. package/harness/commands/eval.md +0 -89
  49. package/harness/commands/go-build.md +0 -87
  50. package/harness/commands/go-review.md +0 -71
  51. package/harness/commands/harness-audit.md +0 -90
  52. package/harness/commands/learn.md +0 -37
  53. package/harness/commands/loop-start.md +0 -38
  54. package/harness/commands/loop-status.md +0 -30
  55. package/harness/commands/memory-search.md +0 -37
  56. package/harness/commands/model-route.md +0 -32
  57. package/harness/commands/ohc.md +0 -13
  58. package/harness/commands/orchestrate.md +0 -88
  59. package/harness/commands/plan.md +0 -53
  60. package/harness/commands/quality-gate.md +0 -35
  61. package/harness/commands/refactor-clean.md +0 -102
  62. package/harness/commands/rust-build.md +0 -78
  63. package/harness/commands/rust-review.md +0 -65
  64. package/harness/commands/security.md +0 -93
  65. package/harness/commands/setup-pm.md +0 -65
  66. package/harness/commands/skill-create.md +0 -99
  67. package/harness/commands/test-coverage.md +0 -80
  68. package/harness/commands/update-codemaps.md +0 -81
  69. package/harness/commands/update-docs.md +0 -67
  70. package/harness/commands/verify.md +0 -68
  71. package/harness/prompts/architect.txt +0 -189
  72. package/harness/prompts/build-cpp.md +0 -98
  73. package/harness/prompts/build-error-resolver.md +0 -44
  74. package/harness/prompts/build-go.md +0 -340
  75. package/harness/prompts/build-java.md +0 -140
  76. package/harness/prompts/build-kotlin.md +0 -137
  77. package/harness/prompts/build-rust.md +0 -108
  78. package/harness/prompts/code-reviewer.md +0 -40
  79. package/harness/prompts/doc-updater.md +0 -206
  80. package/harness/prompts/docs-lookup.md +0 -71
  81. package/harness/prompts/e2e-runner.txt +0 -317
  82. package/harness/prompts/explore.md +0 -42
  83. package/harness/prompts/harness-optimizer.md +0 -42
  84. package/harness/prompts/loop-operator.md +0 -53
  85. package/harness/prompts/planner.md +0 -37
  86. package/harness/prompts/refactor-cleaner.md +0 -256
  87. package/harness/prompts/review-cpp.md +0 -81
  88. package/harness/prompts/review-database.md +0 -261
  89. package/harness/prompts/review-go.md +0 -257
  90. package/harness/prompts/review-java.md +0 -113
  91. package/harness/prompts/review-kotlin.md +0 -143
  92. package/harness/prompts/review-python.md +0 -101
  93. package/harness/prompts/review-rust.md +0 -77
  94. package/harness/prompts/security-reviewer.md +0 -42
  95. package/harness/prompts/tdd-guide.md +0 -228
  96. package/harness/rules/audit.md +0 -84
  97. package/harness/rules/checkpointing.md +0 -75
  98. package/harness/rules/context-loading.md +0 -33
  99. package/harness/rules/credential-exposure.md +0 -0
  100. package/harness/rules/delegation.md +0 -80
  101. package/harness/rules/handoff.md +0 -267
  102. package/harness/rules/memory-management.md +0 -28
  103. package/harness/rules/precedence.md +0 -52
  104. package/harness/rules/promotion.md +0 -46
  105. package/harness/rules/ranking.md +0 -64
  106. package/harness/rules/retrieval.md +0 -94
  107. package/harness/rules/runtime-guards.md +0 -196
  108. package/harness/rules/self-heal.md +0 -79
  109. package/harness/rules/session-start.md +0 -34
  110. package/harness/rules/skills-management.md +0 -165
  111. package/harness/rules/state-drift.md +0 -192
  112. package/harness/rules/verification.md +0 -88
  113. package/harness/scripts/sync-commands.mjs +0 -259
  114. package/harness/skills/.bundled_manifest +0 -17
  115. package/harness/skills/.usage.json +0 -6
  116. package/harness/skills/api-design/SKILL.md +0 -523
  117. package/harness/skills/backend-patterns/SKILL.md +0 -598
  118. package/harness/skills/coding-standards/SKILL.md +0 -549
  119. package/harness/skills/e2e-testing/SKILL.md +0 -326
  120. package/harness/skills/frontend-patterns/SKILL.md +0 -642
  121. package/harness/skills/frontend-slides/SKILL.md +0 -184
  122. package/harness/skills/security-review/SKILL.md +0 -495
  123. package/harness/skills/strategic-compact/SKILL.md +0 -131
  124. package/harness/skills/tdd-workflow/SKILL.md +0 -463
  125. package/harness/skills/verification-loop/SKILL.md +0 -126
  126. package/lib/ambient-memory.mjs +0 -167
  127. package/lib/handoff.mjs +0 -171
  128. package/lib/hardening.mjs +0 -146
  129. package/lib/memory-tools-plugin.mjs +0 -368
  130. package/lib/ohc/block-sync.mjs +0 -69
  131. package/lib/ohc/compress/search.mjs +0 -152
  132. package/lib/ohc/compress/state.mjs +0 -76
  133. package/lib/ohc/config.mjs +0 -185
  134. package/lib/ohc/message-ids.mjs +0 -178
  135. package/lib/ohc/notify.mjs +0 -135
  136. package/lib/ohc/protected-patterns.mjs +0 -55
  137. package/lib/ohc/prune-apply.mjs +0 -134
  138. package/lib/ohc/pruner.mjs +0 -608
  139. package/lib/ohc/reaper.mjs +0 -70
  140. package/lib/ohc/state.mjs +0 -265
  141. package/lib/ohc/strategies/deduplication.mjs +0 -72
  142. package/lib/ohc/strategies/index.mjs +0 -2
  143. package/lib/ohc/strategies/purge-errors.mjs +0 -43
  144. package/lib/ohc/token-utils.mjs +0 -26
  145. package/lib/ohc/updater.mjs +0 -132
  146. package/lib/paths.mjs +0 -49
  147. package/lib/schema-validator.mjs +0 -79
  148. package/lib/search.mjs +0 -48
  149. package/schemas/audit.schema.json +0 -82
  150. package/schemas/backlog.schema.json +0 -63
  151. package/schemas/checkpoint.schema.json +0 -65
  152. package/schemas/constraint.schema.json +0 -62
  153. package/schemas/decision.schema.json +0 -63
  154. package/schemas/instinct.schema.json +0 -63
  155. package/schemas/loop-state.schema.json +0 -33
  156. package/schemas/mistake.schema.json +0 -64
  157. package/schemas/verification_receipt.schema.json +0 -88
  158. package/skill-builder.mjs +0 -88
package/curator.mjs DELETED
@@ -1,482 +0,0 @@
1
- import path from "node:path"
2
- import fs from "node:fs"
3
- import { findUnsupportedSchemaKeywords, validateSchema } from "./lib/schema-validator.mjs"
4
- import { atomicWriteJson, buildEnvironmentFingerprint, fingerprintFile, readJson, redactSensitiveText, sanitizeRecord, truncateText } from "./lib/hardening.mjs"
5
- import { fileURLToPath } from "node:url"
6
- import { dirname } from "node:path"
7
- import { getDataRoot, getMemoryRoot } from "./lib/paths.mjs"
8
-
9
- const __dirname = dirname(fileURLToPath(import.meta.url))
10
-
11
- const CHECKPOINT_DEBOUNCE_MS = 300000
12
- const COMPACTION_CONTEXT_LIMIT = 12000
13
- const lastCheckpoint = { ts: 0 }
14
- const writtenThisSession = []
15
- const CURATOR_LOGS = /^(1|true|yes)$/i.test(process.env.OPENCODE_CURATOR_LOGS || "")
16
-
17
- const MEMORY_CLASSES = ["checkpoints", "mistakes", "audits", "verification_receipts", "constraints", "decisions", "instincts", "backlog"]
18
-
19
- function ensureConsistency(root) {
20
- const memoryRoot = path.join(root, "memory")
21
- const runtimeRoot = path.join(root, "runtime")
22
-
23
- for (const cls of MEMORY_CLASSES) {
24
- const dir = path.join(memoryRoot, cls)
25
- fs.mkdirSync(dir, { recursive: true })
26
- const indexPath = path.join(dir, "index.json")
27
- if (!fs.existsSync(indexPath)) {
28
- atomicWriteJson(indexPath, [])
29
- }
30
- }
31
-
32
- fs.mkdirSync(runtimeRoot, { recursive: true })
33
- const loopStatePath = path.join(runtimeRoot, "loop-state.json")
34
- if (!fs.existsSync(loopStatePath)) {
35
- atomicWriteJson(loopStatePath, { status: "idle", phase: "session.created" })
36
- }
37
- }
38
-
39
- function curatorLog(message) {
40
- if (!CURATOR_LOGS) return
41
- process.stderr.write(`${message}\n`)
42
- }
43
-
44
- function isMeaningfulText(value) {
45
- return typeof value === "string" && value.trim().length > 0 && !/^(n\/a|none|tbd|placeholder|pending|session in progress|no active checkpoint content)$/i.test(value.trim())
46
- }
47
-
48
- function safeLogMessage(message, limit = 160) {
49
- return truncateText(redactSensitiveText(message || ""), limit)
50
- }
51
-
52
- function indexEntry(root, plural, record) {
53
- const indexPath = path.join(root, "memory", plural, "index.json")
54
- let index = readJson(indexPath, [])
55
- if (!Array.isArray(index)) index = []
56
- const entry = {
57
- id: record.id,
58
- summary: record.summary,
59
- status: record.status,
60
- updated_at: record.updated_at || record.created_at,
61
- path: `openhermes/memory/${plural}/${record.id}.json`
62
- }
63
- const existing = index.findIndex(e => e.id === record.id)
64
- if (existing >= 0) index[existing] = entry
65
- else index.push(entry)
66
- atomicWriteJson(indexPath, index)
67
- }
68
-
69
- function updateLoopState(root, patch) {
70
- const statePath = path.join(root, "runtime", "loop-state.json")
71
- const state = readJson(statePath, null) || {}
72
- const next = {
73
- ...state,
74
- ...patch,
75
- updated_at: patch.updated_at || new Date().toISOString(),
76
- }
77
- const schema = loadSchema("loop-state")
78
- if (!schema) return false
79
- const unsupported = findUnsupportedSchemaKeywords(schema)
80
- if (unsupported.length) return false
81
- const errors = validateSchema(schema, next, "$")
82
- if (errors.length) return false
83
- atomicWriteJson(statePath, next)
84
- return true
85
- }
86
-
87
- function loadSchema(classId) {
88
- const fp = path.join(__dirname, "schemas", `${classId}.schema.json`)
89
- try { return JSON.parse(fs.readFileSync(fp, "utf8")) } catch { return null }
90
- }
91
-
92
- function validateRecordAgainstSchema(record) {
93
- const schema = loadSchema(record.class)
94
- if (!schema) {
95
- curatorLog(`[curator] validation fallback: no schema for "${record.class}"`)
96
- const required = record.class === "checkpoint"
97
- ? ["id", "class", "summary", "mission", "current_state", "next_actions", "blockers", "risk_notes", "provenance", "created_at", "status"]
98
- : ["id", "class", "summary", "provenance", "created_at", "status"]
99
- const missing = required.filter(r => !record[r] && record[r] !== null)
100
- if (missing.length) {
101
- curatorLog(`[curator] validation failed: missing ${missing.join(", ")}`)
102
- return false
103
- }
104
- if (record.class === "checkpoint" && record.provenance && !record.provenance.session_id) {
105
- curatorLog(`[curator] validation failed: missing session_id`)
106
- return false
107
- }
108
- return true
109
- }
110
- const unsupported = findUnsupportedSchemaKeywords(schema)
111
- if (unsupported.length) {
112
- curatorLog(`[curator] validation failed: unsupported fields ${unsupported.join(", ")}`)
113
- return false
114
- }
115
- const errors = validateSchema(schema, record, "$")
116
- if (errors.length) {
117
- curatorLog(`[curator] validation failed: ${errors.join("; ")}`)
118
- return false
119
- }
120
- if (record.class === "checkpoint") {
121
- const requiredText = [record.mission, record.current_state]
122
- if (!requiredText.every(isMeaningfulText)) return false
123
- if (!Array.isArray(record.next_actions) || record.next_actions.length === 0) return false
124
- if (!Array.isArray(record.blockers) || record.blockers.length === 0) return false
125
- if (!Array.isArray(record.risk_notes) || record.risk_notes.length === 0) return false
126
- }
127
- return true
128
- }
129
-
130
- async function writeCheckpoint(root, project, directory, trigger, summary, options = {}) {
131
- const now = Date.now()
132
- if (!options.force && now - lastCheckpoint.ts < CHECKPOINT_DEBOUNCE_MS) return null
133
- lastCheckpoint.ts = now
134
-
135
- const ts = new Date().toISOString()
136
- const id = `chk_${ts.replace(/[:.]/g, "-")}`
137
- const environmentFingerprint = buildEnvironmentFingerprint(root, directory, project)
138
- const isCompaction = trigger === "experimental.session.compacting"
139
- const record = {
140
- id,
141
- class: "checkpoint",
142
- scope: "session",
143
- summary: summary || (isCompaction ? `Pre-compaction checkpoint for ${project?.name || path.basename(directory)}` : `Idle checkpoint for ${project?.name || path.basename(directory)}`),
144
- mission: isCompaction
145
- ? "Preserve the current OpenHermes runtime state before compaction trims working context."
146
- : "Preserve the current OpenHermes session state so the next turn can resume safely.",
147
- current_state: isCompaction
148
- ? "A compaction run is starting; runtime memory, recall freshness, and loop-state validation are being hardened before context is reduced."
149
- : "The session is idle and the curator is maintaining durable state, schema validation, and memory hygiene for the next turn.",
150
- next_actions: isCompaction
151
- ? [
152
- "Verify the pre-compaction checkpoint was written and indexed.",
153
- "Inject only fresh recall context into the compaction buffer.",
154
- "Confirm loop-state writes remain schema-valid after compaction.",
155
- ]
156
- : [
157
- "Keep loop-state and memory writes atomic.",
158
- "Redact sensitive text before persisting new records.",
159
- "Recheck stale recall cache handling on the next compaction pass.",
160
- ],
161
- blockers: [
162
- "No blocking runtime failure is present; this checkpoint captures a safe handoff state.",
163
- ],
164
- risk_notes: isCompaction
165
- ? [
166
- "A stale recall cache can reintroduce outdated compaction context if fingerprints drift.",
167
- "Loop-state writes must continue to satisfy the required status, phase, heartbeat_at, and updated_at fields.",
168
- ]
169
- : [
170
- "Placeholder checkpoint content is no longer acceptable for durable handoff.",
171
- "Sensitive text must be redacted before memory persistence.",
172
- ],
173
- provenance: {
174
- session_id: project?.session_id || `session-${Date.now()}`,
175
- harness_root: root,
176
- project_root: directory,
177
- },
178
- description: `Auto-curated checkpoint from curator plugin on ${trigger}`,
179
- source: "agent",
180
- status: "active",
181
- created_at: ts,
182
- updated_at: ts,
183
- project: project?.name || path.basename(directory),
184
- environment_fingerprint: environmentFingerprint,
185
- }
186
- const safeRecord = sanitizeRecord(record, { maxStringLength: 4000 })
187
- if (!validateRecordAgainstSchema(safeRecord)) return null
188
- const dir = path.join(root, "memory", "checkpoints")
189
- atomicWriteJson(path.join(dir, `${id}.json`), safeRecord)
190
- indexEntry(root, "checkpoints", safeRecord)
191
- updateLoopState(root, {
192
- last_checkpoint_id: id,
193
- phase: trigger,
194
- heartbeat_at: ts,
195
- updated_at: ts,
196
- status: trigger === "experimental.session.compacting" ? "active" : "idle",
197
- })
198
- if (writtenThisSession.length >= 100) writtenThisSession.shift()
199
- writtenThisSession.push(id)
200
- curatorLog(`[curator] checkpoint written: ${id} (trigger: ${trigger})`)
201
- return id
202
- }
203
-
204
- function writeMistakeRecord(root, project, directory, error) {
205
- const ts = new Date().toISOString()
206
- const errorMsg = typeof error === "object" && error !== null
207
- ? (error.message || JSON.stringify(error).slice(0, 200))
208
- : (error?.toString() || "Unknown error")
209
- const safeErrorMsg = truncateText(redactSensitiveText(errorMsg), 200)
210
- const id = `mist_${ts.replace(/[:.]/g, "-")}`
211
- const environmentFingerprint = buildEnvironmentFingerprint(root, directory, project)
212
- const record = {
213
- id,
214
- class: "mistake",
215
- scope: "harness",
216
- summary: `Session error: ${safeErrorMsg}`,
217
- failure: `Session error: ${safeErrorMsg}`,
218
- root_cause: safeErrorMsg,
219
- provenance: {
220
- session_id: project?.session_id || `session-${Date.now()}`,
221
- harness_root: root,
222
- project_root: directory,
223
- },
224
- source: "agent",
225
- type: "other",
226
- fix: `Auto-generated - investigate via session_id: ${project?.session_id || "unknown"}`,
227
- prevention: "curator.js writeMistakeRecord must validate against mistake.schema.json",
228
- strike: 1,
229
- status: "active",
230
- created_at: ts,
231
- updated_at: ts,
232
- project: project?.name || path.basename(directory),
233
- environment_fingerprint: environmentFingerprint,
234
- }
235
- const dir = path.join(getMemoryRoot(), "mistakes")
236
- fs.mkdirSync(dir, { recursive: true })
237
- const fp = path.join(dir, "mistakes.jsonl")
238
- const safeRecord = sanitizeRecord(record, { maxStringLength: 4000 })
239
- let entries = []
240
- try { entries = fs.readFileSync(fp, "utf8").trim().split("\n").filter(Boolean).map(l => JSON.parse(l)) } catch {}
241
- const idx = entries.findIndex(e => e.id === safeRecord.id)
242
- if (idx >= 0) entries[idx] = safeRecord; else entries.push(safeRecord)
243
- const text = entries.map(e => JSON.stringify(e)).join("\n")
244
- fs.writeFileSync(fp, text ? text + "\n" : "", "utf8")
245
- curatorLog(`[curator] mistake logged: ${id} - ${safeLogMessage(errorMsg, 80)}`)
246
- return id
247
- }
248
-
249
- function writeVerificationReceipt(root, project, directory, checkpointId) {
250
- const ts = new Date().toISOString()
251
- const id = `vr_${ts.replace(/[:.]/g, "-")}`
252
- const artifactPath = path.join(root, "memory", "checkpoints", `${checkpointId}.json`)
253
- const environmentFingerprint = buildEnvironmentFingerprint(root, directory, project)
254
- const record = {
255
- id,
256
- class: "verification_receipt",
257
- scope: "session",
258
- summary: `Auto-verification receipt for checkpoint ${checkpointId}`,
259
- artifact: `openhermes/memory/checkpoints/${checkpointId}.json`,
260
- artifact_type: "file",
261
- fingerprint: fingerprintFile(artifactPath) || { path: `openhermes/memory/checkpoints/${checkpointId}.json` },
262
- environment: {
263
- cwd: directory,
264
- os: "win32",
265
- shell: "cmd.exe",
266
- provider: "lmstudio"
267
- },
268
- method: "manual-inspection",
269
- command: `curator.js auto-verification on session.idle`,
270
- result: "pass",
271
- result_detail: `Checkpoint ${checkpointId} written and indexed. Session completed successfully.`,
272
- provenance: {
273
- session_id: project?.session_id || `session-${Date.now()}`,
274
- harness_root: root,
275
- project_root: directory,
276
- },
277
- confidence: 0.8,
278
- source: "agent",
279
- status: "active",
280
- created_at: ts,
281
- updated_at: ts,
282
- project: project?.name || path.basename(directory),
283
- environment_fingerprint: environmentFingerprint,
284
- }
285
- const dir = path.join(root, "memory", "verification_receipts")
286
- const safeRecord = sanitizeRecord(record, { maxStringLength: 4000 })
287
- atomicWriteJson(path.join(dir, `${id}.json`), safeRecord)
288
- indexEntry(root, "verification_receipts", safeRecord)
289
- curatorLog(`[curator] verification_receipt written: ${id}`)
290
- return id
291
- }
292
-
293
- async function handleSessionIdle(directory, project) {
294
- try {
295
- const root = getDataRoot()
296
- const checkpointId = await writeCheckpoint(root, project, directory, "session.idle", null)
297
- if (checkpointId) {
298
- writeVerificationReceipt(root, project, directory, checkpointId)
299
- }
300
- } catch (err) {
301
- curatorLog(`[curator] handleSessionIdle error: ${safeLogMessage(err.message)}`)
302
- }
303
- }
304
-
305
- async function handleSessionCompacted(directory, project) {
306
- try {
307
- const root = getDataRoot()
308
- const ts = new Date().toISOString()
309
- updateLoopState(root, {
310
- status: "compacted",
311
- last_gate_result: "compaction completed",
312
- phase: "session.compacted",
313
- heartbeat_at: ts,
314
- updated_at: ts,
315
- })
316
- } catch (err) {
317
- curatorLog(`[curator] handleSessionCompacted error: ${safeLogMessage(err.message)}`)
318
- }
319
- }
320
-
321
- async function handleSessionError(directory, project, event) {
322
- try {
323
- const root = getDataRoot()
324
- const ts = new Date().toISOString()
325
- const errorMsg = typeof event?.error === "object" && event.error !== null
326
- ? (event.error.message || JSON.stringify(event.error).slice(0, 200))
327
- : (event?.error?.toString() || event?.message || "Unknown error")
328
- const safeErrorMsg = safeLogMessage(errorMsg, 200)
329
- updateLoopState(root, {
330
- status: "error",
331
- phase: "session.error",
332
- last_error: safeErrorMsg,
333
- heartbeat_at: ts,
334
- updated_at: ts,
335
- })
336
- writeMistakeRecord(root, project, directory, event.error || event)
337
- } catch (err) {
338
- curatorLog(`[curator] handleSessionError error: ${safeLogMessage(err.message)}`)
339
- }
340
- }
341
-
342
- async function handlePermissionReplied(directory, project, event) {
343
- try {
344
- const root = getDataRoot()
345
- const ts = new Date().toISOString()
346
- const id = `audit_perm_${ts.replace(/[:.]/g, "-")}`
347
- const environmentFingerprint = buildEnvironmentFingerprint(root, directory, project)
348
- const record = {
349
- id,
350
- class: "audit",
351
- scope: "harness",
352
- summary: `Permission reply: ${event.action || "?"} for ${event.tool || "?"}`,
353
- target: event.tool || "unknown",
354
- description: `Permission decision: ${event.action || "?"} - tool: ${event.tool || "?"}, pattern: ${event.pattern || "?"}`,
355
- overall_score: 0,
356
- checks: [
357
- {
358
- name: "permission decision audit",
359
- status: "pass",
360
- details: `Permission ${event.action || "?"} logged for tool ${event.tool || "?"}`,
361
- },
362
- ],
363
- top_actions: [
364
- "Auto-recorded permission event — no manual remediation needed.",
365
- ],
366
- integrity: {
367
- refs_ok: true,
368
- provenance_ok: true,
369
- duplicates_ok: true,
370
- },
371
- provenance: {
372
- session_id: project?.session_id || `session-${Date.now()}`,
373
- harness_root: root,
374
- project_root: directory,
375
- },
376
- source: "agent",
377
- status: "closed",
378
- created_at: ts,
379
- updated_at: ts,
380
- project: project?.name || path.basename(directory),
381
- environment_fingerprint: environmentFingerprint,
382
- }
383
- const safeRecord = sanitizeRecord(record, { maxStringLength: 4000 })
384
- const auditSchema = loadSchema("audit")
385
- if (auditSchema) {
386
- const unsupported = findUnsupportedSchemaKeywords(auditSchema)
387
- if (!unsupported.length) {
388
- const errors = validateSchema(auditSchema, safeRecord, "$")
389
- if (errors.length) return
390
- }
391
- }
392
- const dir = path.join(root, "memory", "audits")
393
- atomicWriteJson(path.join(dir, `${id}.json`), safeRecord)
394
- indexEntry(root, "audits", safeRecord)
395
- curatorLog(`[curator] permission audit logged: ${event.tool} -> ${event.action}`)
396
- } catch (err) {
397
- curatorLog(`[curator] handlePermissionReplied error: ${safeLogMessage(err.message)}`)
398
- }
399
- }
400
-
401
- export const CuratorPlugin = async ({ project, directory }) => {
402
- return {
403
- event: async ({ event }) => {
404
- // A1: v1 migration owned by autorecall.mjs — removed to avoid race
405
- if (event.type === "session.created") {
406
- lastCheckpoint.ts = 0
407
- writtenThisSession.length = 0
408
- try {
409
- const root = getDataRoot()
410
- ensureConsistency(root)
411
- curatorLog("[curator] consistency repair: all memory/runtime dirs verified")
412
- } catch (err) {
413
- curatorLog(`[curator] consistency repair failure: ${safeLogMessage(err.message)}`)
414
- }
415
- }
416
- if (event.type === "session.idle") {
417
- await handleSessionIdle(directory, project)
418
- } else if (event.type === "session.compacted") {
419
- await handleSessionCompacted(directory, project)
420
- } else if (event.type === "session.error") {
421
- await handleSessionError(directory, project, event)
422
- } else if (event.type === "permission.replied") {
423
- await handlePermissionReplied(directory, project, event)
424
- } else if (event.type === "command.executed") {
425
- curatorLog(`[curator] command executed: ${event.command || "?"}`)
426
- }
427
- },
428
- "experimental.session.compacting": async (input, output) => {
429
- try {
430
- const root = getDataRoot()
431
- const projectKey = project?.name || path.basename(directory)
432
- const checkpointIndex = readJson(path.join(root, "memory", "checkpoints", "index.json"), [])
433
- const constraintsIndex = readJson(path.join(root, "memory", "constraints", "index.json"), [])
434
- const environmentFingerprint = buildEnvironmentFingerprint(root, directory, project)
435
- const preCompactionCheckpointId = await writeCheckpoint(root, project, directory, "experimental.session.compacting", `Pre-compaction checkpoint for ${projectKey}`, { force: true })
436
-
437
- const latestCheckpoint = Array.isArray(checkpointIndex) && checkpointIndex.length > 0
438
- ? checkpointIndex.sort((a, b) => new Date(b.updated_at) - new Date(a.updated_at))[0]
439
- : null
440
-
441
- const activeConstraints = Array.isArray(constraintsIndex)
442
- ? constraintsIndex.filter(c => c.status === "active")
443
- : []
444
-
445
- const inject = [
446
- `## OpenHermes State`,
447
- `- Project: ${projectKey}`,
448
- `- Latest checkpoint: ${latestCheckpoint ? latestCheckpoint.summary : "none"}`,
449
- preCompactionCheckpointId ? `- Pre-compaction checkpoint: ${preCompactionCheckpointId}` : null,
450
- `- Active constraints: ${activeConstraints.length}`,
451
- `- Memory writes this session: ${writtenThisSession.length}`,
452
- writtenThisSession.length > 0 ? `- Recent writes: ${writtenThisSession.slice(-3).join(", ")}` : null,
453
- `- Session hook: experimental.session.compacting`,
454
- ].filter(Boolean).join("\n")
455
-
456
- const recallCache = readJson(path.join(root, "memory", "recall", "cache.json"), null)
457
- const cacheMatches = recallCache && recallCache.fingerprint && recallCache.fingerprint.sha256 === environmentFingerprint.sha256
458
- const cacheFresh = cacheMatches && recallCache.freshness_marker && recallCache.freshness_marker.updated_at
459
- ? (Date.now() - Date.parse(recallCache.freshness_marker.updated_at) <= (recallCache.freshness_marker.ttl_ms || 0))
460
- : false
461
- const contextSink = Array.isArray(output.context) ? output.context : (output.context = [])
462
- if (recallCache && recallCache.context && cacheFresh) {
463
- const merged = truncateText(`${inject}\n\n${recallCache.context}`, COMPACTION_CONTEXT_LIMIT)
464
- contextSink.push(merged)
465
- curatorLog(`[curator] compaction injected harness state + autorecall (${merged.length} chars)`)
466
- } else {
467
- contextSink.push(truncateText(inject, COMPACTION_CONTEXT_LIMIT))
468
- curatorLog(`[curator] compaction injected harness state (stale or missing autorecall cache)`)
469
- }
470
- updateLoopState(root, {
471
- phase: "compress",
472
- heartbeat_at: new Date().toISOString(),
473
- status: "active",
474
- })
475
- } catch (err) {
476
- curatorLog(`[curator] compaction error: ${safeLogMessage(err.message)}`)
477
- const contextSink = Array.isArray(output.context) ? output.context : (output.context = [])
478
- contextSink.push(truncateText(`## OpenHermes State\n- Project: ${project?.name || path.basename(directory)}\n- Hook: experimental.session.compacting (error state)\n`, COMPACTION_CONTEXT_LIMIT))
479
- }
480
- },
481
- }
482
- }
@@ -1,60 +0,0 @@
1
- ---
2
- description: Fix build and TypeScript errors with minimal changes
3
- agent: build-error-resolver
4
- subtask: true
5
- ---
6
-
7
- # Build Fix Command
8
-
9
- Fix build and TypeScript errors with minimal changes: $ARGUMENTS
10
-
11
- ## Current type errors
12
-
13
- !npx tsc --noEmit 2>&1 || echo "tsc not available or no errors"
14
-
15
- ## Your Task
16
-
17
- 1. **Run type check**: `npx tsc --noEmit`
18
- 2. **Collect all errors**
19
- 3. **Fix errors one by one** with minimal changes
20
- 4. **Verify each fix** doesn't introduce new errors
21
- 5. **Run final check** to confirm all errors resolved
22
-
23
- ## Approach
24
-
25
- ### DO:
26
- - PASS: Fix type errors with correct types
27
- - PASS: Add missing imports
28
- - PASS: Fix syntax errors
29
- - PASS: Make minimal changes
30
- - PASS: Preserve existing behavior
31
- - PASS: Run `tsc --noEmit` after each change
32
-
33
- ### DON'T:
34
- - FAIL: Refactor code
35
- - FAIL: Add new features
36
- - FAIL: Change architecture
37
- - FAIL: Use `any` type (unless absolutely necessary)
38
- - FAIL: Add `@ts-ignore` comments
39
- - FAIL: Change business logic
40
-
41
- ## Common Error Fixes
42
-
43
- | Error | Fix |
44
- |-------|-----|
45
- | Type 'X' is not assignable to type 'Y' | Add correct type annotation |
46
- | Property 'X' does not exist | Add property to interface or fix property name |
47
- | Cannot find module 'X' | Install package or fix import path |
48
- | Argument of type 'X' is not assignable | Cast or fix function signature |
49
- | Object is possibly 'undefined' | Add null check or optional chaining |
50
-
51
- ## Verification Steps
52
-
53
- After fixes:
54
- 1. `npx tsc --noEmit` - should show 0 errors
55
- 2. `npm run build` - should succeed
56
- 3. `npm test` - tests should still pass
57
-
58
- ---
59
-
60
- **IMPORTANT**: Focus on fixing errors only. No refactoring, no improvements, no architectural changes. Get the build green with minimal diff.
@@ -1,68 +0,0 @@
1
- ---
2
- description: Save verification state and progress checkpoint
3
- agent: OpenHermes
4
- subtask: true
5
- ---
6
-
7
- # Checkpoint Command
8
-
9
- Save current verification state and create progress checkpoint: $ARGUMENTS
10
-
11
- ## Your Task
12
-
13
- Create a snapshot of current progress including:
14
-
15
- 1. **Tests status** - Which tests pass/fail
16
- 2. **Coverage** - Current coverage metrics
17
- 3. **Build status** - Build succeeds or errors
18
- 4. **Code changes** - Summary of modifications
19
- 5. **Next steps** - What remains to be done
20
-
21
- ## Checkpoint Format
22
-
23
- ### Checkpoint: [Timestamp]
24
-
25
- **Tests**
26
- - Total: X
27
- - Passing: Y
28
- - Failing: Z
29
- - Coverage: XX%
30
-
31
- **Build**
32
- - Status: PASS: Passing / FAIL: Failing
33
- - Errors: [if any]
34
-
35
- **Changes Since Last Checkpoint**
36
- ```
37
- git diff --stat [last-checkpoint-commit]
38
- ```
39
-
40
- **Completed Tasks**
41
- - [x] Task 1
42
- - [x] Task 2
43
- - [ ] Task 3 (in progress)
44
-
45
- **Blocking Issues**
46
- - [Issue description]
47
-
48
- **Next Steps**
49
- 1. Step 1
50
- 2. Step 2
51
-
52
- ## Usage with Verification Loop
53
-
54
- Checkpoints integrate with the verification loop:
55
-
56
- ```
57
- /plan → implement → /checkpoint → /verify → /checkpoint → implement → ...
58
- ```
59
-
60
- Use checkpoints to:
61
- - Save state before risky changes
62
- - Track progress through phases
63
- - Enable rollback if needed
64
- - Document verification points
65
-
66
- ---
67
-
68
- **TIP**: Create checkpoints at natural breakpoints: after each phase, before major refactoring, after fixing critical bugs.
@@ -1,71 +0,0 @@
1
- ---
2
- description: Review code for quality, security, and maintainability
3
- agent: code-reviewer
4
- subtask: true
5
- ---
6
-
7
- # Code Review Command
8
-
9
- Review code changes for quality, security, and maintainability: $ARGUMENTS
10
-
11
- ## Changed files
12
-
13
- !git diff --name-only HEAD 2>&1 || echo "No git repo or no changes"
14
-
15
- ## Your Task
16
-
17
- 1. **Analyze each changed file** for issues
18
- 3. **Generate structured report**
19
- 4. **Provide actionable recommendations**
20
-
21
- ## Check Categories
22
-
23
- ### Security Issues (CRITICAL)
24
- - [ ] Hardcoded credentials, API keys, tokens
25
- - [ ] SQL injection vulnerabilities
26
- - [ ] XSS vulnerabilities
27
- - [ ] Missing input validation
28
- - [ ] Insecure dependencies
29
- - [ ] Path traversal risks
30
- - [ ] Authentication/authorization flaws
31
-
32
- ### Code Quality (HIGH)
33
- - [ ] Functions > 50 lines
34
- - [ ] Files > 800 lines
35
- - [ ] Nesting depth > 4 levels
36
- - [ ] Missing error handling
37
- - [ ] console.log statements
38
- - [ ] TODO/FIXME comments
39
- - [ ] Missing JSDoc for public APIs
40
-
41
- ### Best Practices (MEDIUM)
42
- - [ ] Mutation patterns (use immutable instead)
43
- - [ ] Unnecessary complexity
44
- - [ ] Missing tests for new code
45
- - [ ] Accessibility issues (a11y)
46
- - [ ] Performance concerns
47
-
48
- ### Style (LOW)
49
- - [ ] Inconsistent naming
50
- - [ ] Missing type annotations
51
- - [ ] Formatting issues
52
-
53
- ## Report Format
54
-
55
- For each issue found:
56
-
57
- ```
58
- **[SEVERITY]** file.ts:123
59
- Issue: [Description]
60
- Fix: [How to fix]
61
- ```
62
-
63
- ## Decision
64
-
65
- - **CRITICAL or HIGH issues**: Block commit, require fixes
66
- - **MEDIUM issues**: Recommend fixes before merge
67
- - **LOW issues**: Optional improvements
68
-
69
- ---
70
-
71
- **IMPORTANT**: Never approve code with security vulnerabilities!