openhermes 2.6.1 → 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.
- package/CONTEXT.md +18 -0
- package/ETHOS.md +15 -0
- package/README.md +135 -292
- package/bootstrap.mjs +174 -499
- 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 +157 -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 -58
- 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 -455
- 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 -176
- package/lib/hardening.mjs +0 -128
- package/lib/memory-tools-plugin.mjs +0 -365
- 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 -186
- package/lib/ohc/message-ids.mjs +0 -168
- package/lib/ohc/notify.mjs +0 -154
- package/lib/ohc/protected-patterns.mjs +0 -54
- package/lib/ohc/prune-apply.mjs +0 -134
- package/lib/ohc/pruner.mjs +0 -610
- package/lib/ohc/reaper.mjs +0 -70
- package/lib/ohc/state.mjs +0 -266
- 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 -133
- package/lib/paths.mjs +0 -50
- package/lib/schema-validator.mjs +0 -77
- 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
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
# Verification — Skeptical Evidence Protocol
|
|
2
|
-
|
|
3
|
-
Constitutional parent: principle 11 (`openhermes\codex\CONSTITUTION.md`).
|
|
4
|
-
Trust nothing without evidence. Every claim, instruction, document, and behavioral assertion must be confirmed by personal observation or a cached verification receipt before it may be treated as ground truth.
|
|
5
|
-
|
|
6
|
-
Verification receipts prove that an artifact was observed in a particular state. They do not, by themselves, prove a live runtime claim unless the receipt captures a live-session artifact or log.
|
|
7
|
-
|
|
8
|
-
## Core Stance
|
|
9
|
-
|
|
10
|
-
- **User claims** — Input, not truth. Verify against evidence before acting.
|
|
11
|
-
- **Document claims** — Documents rot. Cross-reference against current filesystem/code state.
|
|
12
|
-
- **Code/script claims** — Past success does not guarantee present function. Run and check.
|
|
13
|
-
- **Dependency claims** — Package manifests can be stale. Check the filesystem directly.
|
|
14
|
-
|
|
15
|
-
## Verification Cache (Memory-Backed)
|
|
16
|
-
|
|
17
|
-
Successful verifications are stored via `ohc_save` so repeated checks of unchanged artifacts are skipped.
|
|
18
|
-
|
|
19
|
-
### Cache Key
|
|
20
|
-
|
|
21
|
-
Each verification receipt is keyed by:
|
|
22
|
-
- **Artifact identity**: normalized file path, or logical identity (e.g., `state:dcp-installed`)
|
|
23
|
-
- **Artifact fingerprint**: file `mtime` + `size` (files), or structured state hash (logical)
|
|
24
|
-
|
|
25
|
-
### Cache Lifecycle
|
|
26
|
-
|
|
27
|
-
1. **Before trusting a claim**: search memory (`ohc_get` or `ohc_list`) for matching receipt.
|
|
28
|
-
2. **Receipt found + fingerprint matches**: artifact unchanged. Trust cached result. Skip re-verify.
|
|
29
|
-
3. **Receipt found + fingerprint differs**: artifact changed. Re-verify. Stale receipt is invalid.
|
|
30
|
-
4. **No receipt found**: verify fresh. Store receipt on success.
|
|
31
|
-
|
|
32
|
-
### Receipt Storage
|
|
33
|
-
|
|
34
|
-
Use `ohc_save` with class `verification_receipt` — a dedicated memory class (schema: `schemas\verification_receipt.schema.json`). Receipts are stored as file-per-object in `memory\verification_receipts\<id>.json`.
|
|
35
|
-
|
|
36
|
-
Required fields:
|
|
37
|
-
- **artifact**: path or logical identity of the verified artifact
|
|
38
|
-
- **fingerprint**: { path, mtime, size, sha256? } — determines cache validity
|
|
39
|
-
- **environment**: { cwd, os, shell, provider, model } — reproducibility context
|
|
40
|
-
- **method**: "command" | "read" | "test" | "schema-validate" | "manual-inspection" | "bash" | "grep"
|
|
41
|
-
- **result**: "pass" | "fail" | "unknown"
|
|
42
|
-
- **result_detail**: free-text description of what passed/failed, including output excerpts for command-based methods
|
|
43
|
-
- **expires_at**: ISO-8601 — hard expiry regardless of fingerprint match (default: 30 days)
|
|
44
|
-
- **supersedes / superseded_by**: receipt chains for audit trail
|
|
45
|
-
|
|
46
|
-
Receipt quality gates:
|
|
47
|
-
1. Every receipt must have: `artifact`, `method`, `result`, `result_detail`, `fingerprint`, `environment`, `provenance.session_id`, `created_at`.
|
|
48
|
-
2. Command-based receipts (`method: command | bash | test`) must include output excerpt or exit code in `result_detail`.
|
|
49
|
-
3. Config-based receipts (`method: manual-inspection | schema-validate | grep`) must reference the specific file paths inspected.
|
|
50
|
-
4. No receipt may exceed 30 lines. If more detail is needed, link to a file.
|
|
51
|
-
5. Receipts that supersede older ones must set `supersedes` to the prior receipt ID. The older receipt gets `superseded_by`.
|
|
52
|
-
6. Receipts without `fingerprint` are non-cacheable — they must be re-verified every time.
|
|
53
|
-
|
|
54
|
-
Receipts stored under `decision` with `v:` prefix are deprecated. Migrate to `verification_receipt` class on next touch.
|
|
55
|
-
|
|
56
|
-
## Verification Methods by Artifact
|
|
57
|
-
|
|
58
|
-
| Artifact | Method | Evidence |
|
|
59
|
-
|---|---|---|
|
|
60
|
-
| File content | `read` + grep for expected text | Exact match |
|
|
61
|
-
| Code behavior | `bash` with test command | Exit 0 + expected output |
|
|
62
|
-
| Directory structure | `read` (dir) or `glob` | Entry list matches |
|
|
63
|
-
| Installation state | `bash (cmd --version)` | Non-error + expected version |
|
|
64
|
-
| Document truth | Cross-ref code/filesystem | Primary source confirms doc |
|
|
65
|
-
| User claim | Execute/read referenced thing | Primary evidence matches claim |
|
|
66
|
-
|
|
67
|
-
## Contradiction Protocol
|
|
68
|
-
|
|
69
|
-
When verification reveals evidence contradicts a document or user claim:
|
|
70
|
-
|
|
71
|
-
1. **Pause** — do not proceed on either source.
|
|
72
|
-
2. **Log** — `ohc_save` as `constraint` or `backlog` with both claim and contradictory evidence.
|
|
73
|
-
3. **Flag** — ask user about the discrepancy. Present both sides.
|
|
74
|
-
4. **Resolve** — let user decide which source is authoritative. Update document if needed.
|
|
75
|
-
|
|
76
|
-
## When to Skip Verification
|
|
77
|
-
|
|
78
|
-
Allowed ONLY when:
|
|
79
|
-
- Cached receipt with matching fingerprint exists in memory, AND
|
|
80
|
-
- Artifact is confirmed unchanged (same mtime/hash)
|
|
81
|
-
|
|
82
|
-
Never skip based on "should work" or "user says it works."
|
|
83
|
-
|
|
84
|
-
## Integration
|
|
85
|
-
|
|
86
|
-
- **Precedence** (`rules/precedence.md`): verified claim outranks unverified claim at same level. A verification receipt raises the effective priority of the claim it supports.
|
|
87
|
-
- **Memory Retrieval** (`rules/retrieval.md`): verification receipts are queried before substantive work (Gate 2) and before task close (Gate 3).
|
|
88
|
-
- **Self-Edit** (`AGENTS.md` Self-Edit Authority): adding verification receipts is unconditionally allowed.
|
|
@@ -1,259 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import fs from "node:fs"
|
|
3
|
-
import path from "node:path"
|
|
4
|
-
import { fileURLToPath } from "node:url"
|
|
5
|
-
|
|
6
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
|
7
|
-
const REPO_ROOT = path.resolve(__dirname, "..", "..")
|
|
8
|
-
const COMMANDS_DIR = path.join(REPO_ROOT, "harness", "commands")
|
|
9
|
-
const BOOTSTRAP_FILE = path.join(REPO_ROOT, "bootstrap.mjs")
|
|
10
|
-
const README_FILE = path.join(REPO_ROOT, "README.md")
|
|
11
|
-
|
|
12
|
-
const COMMANDS_START = "<!-- COMMANDS:START -->"
|
|
13
|
-
const COMMANDS_END = "<!-- COMMANDS:END -->"
|
|
14
|
-
|
|
15
|
-
const HOOK_ONLY = new Set(["update-me"])
|
|
16
|
-
|
|
17
|
-
function parseRegistry(src) {
|
|
18
|
-
const commands = {}
|
|
19
|
-
const blockMatch = src.match(/config\.command\s*=\s*\{([\s\S]*?)\n\s*\}/)
|
|
20
|
-
if (!blockMatch) return commands
|
|
21
|
-
|
|
22
|
-
let rest = blockMatch[1]
|
|
23
|
-
const entryRe = /^\s*"([^"]+)"\s*:\s*\{([\s\S]*?)\},?\s*$/gm
|
|
24
|
-
let m
|
|
25
|
-
while ((m = entryRe.exec(rest)) !== null) {
|
|
26
|
-
const name = m[1]
|
|
27
|
-
const body = m[2]
|
|
28
|
-
const agent = body.match(/agent:\s*"([^"]+)"/)?.[1] ?? ""
|
|
29
|
-
const description = body.match(/description:\s*"([^"]+)"/)?.[1] ?? ""
|
|
30
|
-
const template = body.match(/template:\s*ct\("([^"]+)"\)/) ? m[0].match(/template:\s*(ct\("[^"]+"\)|""|'')/)?.[1] : ""
|
|
31
|
-
const hasFile = template.includes("ct(")
|
|
32
|
-
commands[name] = { name, agent, description, hasFile }
|
|
33
|
-
}
|
|
34
|
-
return commands
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
function parseCommandFile(filePath) {
|
|
38
|
-
const src = fs.readFileSync(filePath, "utf8")
|
|
39
|
-
const name = path.basename(filePath, ".md")
|
|
40
|
-
const description = src.match(/^description:\s*(.+)$/m)?.[1] ?? ""
|
|
41
|
-
const agent = src.match(/^agent:\s*(.+)$/m)?.[1] ?? ""
|
|
42
|
-
return { name, description, agent }
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
function scanCommandFiles() {
|
|
46
|
-
const files = fs.readdirSync(COMMANDS_DIR).filter(f => f.endsWith(".md"))
|
|
47
|
-
const map = {}
|
|
48
|
-
for (const f of files) {
|
|
49
|
-
const parsed = parseCommandFile(path.join(COMMANDS_DIR, f))
|
|
50
|
-
map[parsed.name] = parsed
|
|
51
|
-
}
|
|
52
|
-
return map
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
function getHookCommands() {
|
|
56
|
-
return [...HOOK_ONLY].map(name => ({ name, agent: "", description: "Hook-handled (see plugin source)" }))
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
function printReport(registry, filesOnDisk, hookCommands, cmdNames) {
|
|
60
|
-
console.log("")
|
|
61
|
-
console.log(" COMMAND SYNC REPORT")
|
|
62
|
-
console.log(" " + "=".repeat(50))
|
|
63
|
-
const registered = new Set(Object.keys(registry))
|
|
64
|
-
const onDisk = new Set(Object.keys(filesOnDisk))
|
|
65
|
-
const allHooks = new Set(hookCommands.map(h => h.name))
|
|
66
|
-
const hookNoReg = [...allHooks].filter(n => !registered.has(n) && !onDisk.has(n))
|
|
67
|
-
|
|
68
|
-
console.log(` Registered in bootstrap.mjs: ${registered.size}`)
|
|
69
|
-
console.log(` Files in harness/commands/: ${onDisk.size}`)
|
|
70
|
-
console.log(` Hook-only (no registry): ${hookNoReg.length}`)
|
|
71
|
-
console.log(` Total real commands: ${cmdNames.length}`)
|
|
72
|
-
console.log("")
|
|
73
|
-
|
|
74
|
-
const registeredNoFile = [...registered].filter(n => !onDisk.has(n))
|
|
75
|
-
const fileNotRegistered = [...onDisk].filter(n => !registered.has(n) && !allHooks.has(n))
|
|
76
|
-
|
|
77
|
-
if (registeredNoFile.length) {
|
|
78
|
-
console.log(" ⚠ REGISTERED, NO FILE:")
|
|
79
|
-
for (const n of registeredNoFile) {
|
|
80
|
-
const e = registry[n]
|
|
81
|
-
console.log(` /${n} — ${e.description}`)
|
|
82
|
-
}
|
|
83
|
-
console.log("")
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
if (fileNotRegistered.length) {
|
|
87
|
-
console.log(" ⚠ FILE EXISTS, NOT REGISTERED:")
|
|
88
|
-
for (const n of fileNotRegistered) {
|
|
89
|
-
console.log(` /${n}`)
|
|
90
|
-
}
|
|
91
|
-
console.log("")
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
if (hookNoReg.length) {
|
|
95
|
-
console.log(" ℹ HOOK-ONLY (no registry, no file):")
|
|
96
|
-
for (const n of hookNoReg) {
|
|
97
|
-
console.log(` /${n}`)
|
|
98
|
-
}
|
|
99
|
-
console.log("")
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
if (!registeredNoFile.length && !fileNotRegistered.length) {
|
|
103
|
-
console.log(" ✓ Everything in sync — no gaps.")
|
|
104
|
-
console.log("")
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
function generateMissingFiles(registry, filesOnDisk) {
|
|
109
|
-
let count = 0
|
|
110
|
-
for (const [name, entry] of Object.entries(registry)) {
|
|
111
|
-
if (filesOnDisk[name]) continue
|
|
112
|
-
|
|
113
|
-
const templateFile = `${name}.md`
|
|
114
|
-
const agent = entry.agent || "OpenHermes"
|
|
115
|
-
const desc = entry.description
|
|
116
|
-
|
|
117
|
-
let md = `---
|
|
118
|
-
description: ${desc}
|
|
119
|
-
agent: ${agent}
|
|
120
|
-
subtask: true
|
|
121
|
-
---
|
|
122
|
-
|
|
123
|
-
# ${name.charAt(0).toUpperCase() + name.slice(1)} Command
|
|
124
|
-
|
|
125
|
-
`
|
|
126
|
-
|
|
127
|
-
if (name === "ohc") {
|
|
128
|
-
md += `OHC context management — hook-handled.\n\nRun \`/ohc status\` to check context usage, \`/ohc compress [targetTokens] [focus]\` to free space.\n\n$ARGUMENTS\n`
|
|
129
|
-
} else {
|
|
130
|
-
md += `${desc}: $ARGUMENTS\n`
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
fs.writeFileSync(path.join(COMMANDS_DIR, templateFile), md, "utf8")
|
|
134
|
-
console.log(` ✓ Created harness/commands/${templateFile}`)
|
|
135
|
-
count++
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
if (count === 0) console.log(" No missing files to generate.")
|
|
139
|
-
return count
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
function getCommandNames(registry, hookCommands) {
|
|
143
|
-
const registered = new Set(Object.keys(registry))
|
|
144
|
-
const hookOnly = hookCommands.filter(h => !registered.has(h.name)).map(h => h.name)
|
|
145
|
-
const names = [...registered, ...hookOnly]
|
|
146
|
-
names.sort()
|
|
147
|
-
return names
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
function formatCommandRow(names) {
|
|
151
|
-
const count = names.length
|
|
152
|
-
const list = names.map(n => `\`/${n}\``).join(", ")
|
|
153
|
-
return `| **${count} slash commands** | ${list} |`
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
function formatBacktickList(names) {
|
|
157
|
-
return ` ${names.map(n => `\\\`/${n}\\\``).join(", ")}`
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
function syncBootstrap(registry, hookCommands) {
|
|
161
|
-
let src = fs.readFileSync(BOOTSTRAP_FILE, "utf8")
|
|
162
|
-
const cmdNames = getCommandNames(registry, hookCommands)
|
|
163
|
-
const row = formatCommandRow(cmdNames)
|
|
164
|
-
|
|
165
|
-
const startIdx = src.indexOf(COMMANDS_START)
|
|
166
|
-
const endIdx = src.indexOf(COMMANDS_END)
|
|
167
|
-
|
|
168
|
-
if (startIdx === -1 || endIdx === -1) {
|
|
169
|
-
console.log(" ✗ Markers not found in bootstrap.mjs. Inserting markers.")
|
|
170
|
-
const plugRowRe = /(\|\s+\*\*Plugins\s*\*\*.*\|)/
|
|
171
|
-
const match = src.match(plugRowRe)
|
|
172
|
-
if (!match) {
|
|
173
|
-
console.log(" ✗ Could not find Plugins row to anchor insertion.")
|
|
174
|
-
return false
|
|
175
|
-
}
|
|
176
|
-
const insertAfter = match.index + match[0].length
|
|
177
|
-
const newRow = `\n| **Slash commands** | ${COMMANDS_START} ${COMMANDS_END} |`
|
|
178
|
-
src = src.slice(0, insertAfter) + newRow + src.slice(insertAfter)
|
|
179
|
-
// Re-find markers for content replacement below
|
|
180
|
-
const newStart = src.indexOf(COMMANDS_START)
|
|
181
|
-
const newEnd = src.indexOf(COMMANDS_END)
|
|
182
|
-
if (newStart !== -1 && newEnd !== -1 && newEnd > newStart) {
|
|
183
|
-
const content = formatBacktickList(cmdNames)
|
|
184
|
-
src = src.slice(0, newStart + COMMANDS_START.length) + content + src.slice(newEnd)
|
|
185
|
-
}
|
|
186
|
-
fs.writeFileSync(BOOTSTRAP_FILE, src, "utf8")
|
|
187
|
-
console.log(" ✓ Inserted Slash commands row in bootstrap.mjs")
|
|
188
|
-
return true
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
if (endIdx <= startIdx) {
|
|
192
|
-
console.log(" ✗ Markers out of order in bootstrap.mjs")
|
|
193
|
-
return false
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
const content = formatBacktickList(cmdNames)
|
|
197
|
-
src = src.slice(0, startIdx + COMMANDS_START.length) + content + src.slice(endIdx)
|
|
198
|
-
fs.writeFileSync(BOOTSTRAP_FILE, src, "utf8")
|
|
199
|
-
console.log(" ✓ Updated Slash commands row in bootstrap.mjs")
|
|
200
|
-
return true
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
function syncReadme(registry, hookCommands) {
|
|
204
|
-
let src = fs.readFileSync(README_FILE, "utf8")
|
|
205
|
-
const cmdNames = getCommandNames(registry, hookCommands)
|
|
206
|
-
const row = formatCommandRow(cmdNames)
|
|
207
|
-
|
|
208
|
-
const tableRowRe = /^\|\s*\*\*(\d+)\s*slash commands\s*\*\*.*\|$/m
|
|
209
|
-
const match = src.match(tableRowRe)
|
|
210
|
-
if (!match) {
|
|
211
|
-
console.log(" ✗ Could not find slash commands row in README.md")
|
|
212
|
-
return false
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
src = src.replace(tableRowRe, row)
|
|
216
|
-
fs.writeFileSync(README_FILE, src, "utf8")
|
|
217
|
-
console.log(` ✓ Updated README.md: ${cmdNames.length} commands`)
|
|
218
|
-
return true
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
// Main
|
|
222
|
-
const args = process.argv.slice(2)
|
|
223
|
-
const doAudit = args.includes("--audit") || args.length === 0
|
|
224
|
-
const doGenerate = args.includes("--generate") || args.length === 0
|
|
225
|
-
const doSyncBootstrap = args.includes("--sync-bootstrap") || args.includes("--sync") || args.length === 0
|
|
226
|
-
const doSyncReadme = args.includes("--sync-readme") || args.includes("--sync") || args.length === 0
|
|
227
|
-
|
|
228
|
-
console.log(" ▸ syncing command definitions...")
|
|
229
|
-
console.log("")
|
|
230
|
-
|
|
231
|
-
const bootstrapSrc = fs.readFileSync(BOOTSTRAP_FILE, "utf8")
|
|
232
|
-
const registry = parseRegistry(bootstrapSrc)
|
|
233
|
-
const filesOnDisk = scanCommandFiles()
|
|
234
|
-
const hookCommands = getHookCommands()
|
|
235
|
-
const cmdNames = getCommandNames(registry, hookCommands)
|
|
236
|
-
|
|
237
|
-
if (doAudit) printReport(registry, filesOnDisk, hookCommands, cmdNames)
|
|
238
|
-
|
|
239
|
-
if (doGenerate) {
|
|
240
|
-
console.log(" [generate]")
|
|
241
|
-
generateMissingFiles(registry, filesOnDisk)
|
|
242
|
-
console.log("")
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
if (doSyncBootstrap) {
|
|
246
|
-
console.log(" [sync-bootstrap]")
|
|
247
|
-
const ok = syncBootstrap(registry, hookCommands)
|
|
248
|
-
if (!ok) process.exitCode = 1
|
|
249
|
-
console.log("")
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
if (doSyncReadme) {
|
|
253
|
-
console.log(" [sync-readme]")
|
|
254
|
-
const ok = syncReadme(registry, hookCommands)
|
|
255
|
-
if (!ok) process.exitCode = 1
|
|
256
|
-
console.log("")
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
console.log(" done.")
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 1,
|
|
3
|
-
"description": "Bundled skills shipped with openhermes. These are never subject to curator mutation, archive, or deletion.",
|
|
4
|
-
"skills": [
|
|
5
|
-
{ "name": "api-design", "bundled": true, "created_by": "openhermes" },
|
|
6
|
-
{ "name": "backend-patterns", "bundled": true, "created_by": "openhermes" },
|
|
7
|
-
{ "name": "coding-standards", "bundled": true, "created_by": "openhermes" },
|
|
8
|
-
{ "name": "e2e-testing", "bundled": true, "created_by": "openhermes" },
|
|
9
|
-
{ "name": "frontend-patterns", "bundled": true, "created_by": "openhermes" },
|
|
10
|
-
{ "name": "frontend-slides", "bundled": true, "created_by": "openhermes" },
|
|
11
|
-
{ "name": "security-review", "bundled": true, "created_by": "openhermes" },
|
|
12
|
-
{ "name": "strategic-compact", "bundled": true, "created_by": "openhermes" },
|
|
13
|
-
{ "name": "tdd-workflow", "bundled": true, "created_by": "openhermes" },
|
|
14
|
-
{ "name": "verification-loop", "bundled": true, "created_by": "openhermes" }
|
|
15
|
-
],
|
|
16
|
-
"updated_at": "2026-05-08T00:00:00Z"
|
|
17
|
-
}
|