opencode-overclock 0.4.0 → 0.5.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/README.md +72 -17
- package/package.json +5 -3
- package/skills/codebase-design/DEEPENING.md +35 -0
- package/skills/codebase-design/DESIGN-IT-TWICE.md +34 -0
- package/skills/codebase-design/SKILL.md +93 -0
- package/skills/diagnosing-bugs/SKILL.md +123 -0
- package/skills/domain-modeling/ADR-FORMAT.md +55 -0
- package/skills/domain-modeling/CONTEXT-FORMAT.md +32 -0
- package/skills/domain-modeling/SKILL.md +102 -0
- package/skills/doubt/SKILL.md +80 -0
- package/skills/grilling/SKILL.md +96 -0
- package/skills/source-discipline/SKILL.md +78 -0
- package/skills/tdd/SKILL.md +87 -0
- package/skills/to-spec/SKILL.md +69 -0
- package/skills/to-spec/SPEC-TEMPLATE.md +50 -0
- package/skills/to-tickets/SKILL.md +74 -0
- package/skills/to-tickets/TICKET-TEMPLATE.md +41 -0
- package/src/core/lifecycle.ts +18 -4
- package/src/core/types.ts +29 -0
- package/src/features/guard.ts +258 -12
- package/src/features/index.ts +13 -1
- package/src/features/recovery.ts +13 -3
- package/src/features/safety.ts +147 -0
- package/src/features/sched.ts +46 -10
- package/src/features/tasks.ts +87 -20
- package/src/features/truncator.ts +26 -9
- package/src/features/usage.ts +20 -0
- package/src/features/workflow.ts +270 -0
- package/src/lib/exec.ts +7 -1
- package/src/platform/process/exec.ts +252 -11
- package/src/platform/session/inject.ts +8 -1
- package/src/platform/storage/state.ts +26 -4
- package/src/v2/host.ts +4 -1
- package/src/workflow/agents/codebase-researcher.ts +27 -0
- package/src/workflow/agents/craftsman.ts +26 -0
- package/src/workflow/agents/design-explorer.ts +33 -0
- package/src/workflow/agents/doc-writer.ts +24 -0
- package/src/workflow/agents/doubt-reviewer.ts +26 -0
- package/src/workflow/agents/engineering-coach.ts +23 -0
- package/src/workflow/agents/performance-auditor.ts +29 -0
- package/src/workflow/agents/security-auditor.ts +23 -0
- package/src/workflow/agents/spec-reviewer.ts +15 -0
- package/src/workflow/agents/standards-reviewer.ts +24 -0
- package/src/workflow/agents/test-engineer.ts +28 -0
- package/src/workflow/catalog.ts +210 -0
- package/src/workflow/templates/build.ts +47 -0
- package/src/workflow/templates/define.ts +45 -0
- package/src/workflow/templates/diagnose.ts +58 -0
- package/src/workflow/templates/plan.ts +52 -0
- package/src/workflow/templates/ship.ts +64 -0
|
@@ -14,11 +14,239 @@ export const NON_INTERACTIVE_ENV: Record<string, string> = {
|
|
|
14
14
|
TERM: "dumb",
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
+
/**
|
|
18
|
+
* Pattern matching environment variable names that typically store credentials,
|
|
19
|
+
* secrets, authentication tokens, API keys, or private keys.
|
|
20
|
+
*/
|
|
21
|
+
export const SENSITIVE_ENV_PATTERN =
|
|
22
|
+
/(?:KEY|SECRET|TOKEN|AUTH|PASS(?:WORD|WD)?|CREDENTIAL|PRIVATE|SIGNING|DATABASE_URL|WEBHOOK|CERT|BEARER|COOKIE)/i
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Known system and transport variables that match sensitive keywords but are
|
|
26
|
+
* necessary for everyday development operations (SSH agent socket, TLS certificates).
|
|
27
|
+
*/
|
|
28
|
+
export const DEFAULT_PRESERVED_ENV: readonly string[] = [
|
|
29
|
+
"SSH_AUTH_SOCK",
|
|
30
|
+
"SSL_CERT_FILE",
|
|
31
|
+
"SSL_CERT_DIR",
|
|
32
|
+
"NODE_EXTRA_CA_CERTS",
|
|
33
|
+
"GIT_SSH_COMMAND",
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Filter an environment map to remove sensitive keys (API keys, secrets, tokens).
|
|
38
|
+
* Safe system and build variables (PATH, HOME, USER, SHELL, TEMP, LANG, etc.)
|
|
39
|
+
* as well as essential operational credentials (SSH_AUTH_SOCK, certificates) are preserved.
|
|
40
|
+
*/
|
|
41
|
+
export function sanitizeEnv(
|
|
42
|
+
env: Record<string, string | undefined>,
|
|
43
|
+
allowlist?: string[],
|
|
44
|
+
): Record<string, string | undefined> {
|
|
45
|
+
const allowed = new Set([
|
|
46
|
+
...DEFAULT_PRESERVED_ENV.map((k) => k.toUpperCase()),
|
|
47
|
+
...(allowlist?.map((k) => k.toUpperCase()) ?? []),
|
|
48
|
+
])
|
|
49
|
+
const sanitized: Record<string, string | undefined> = {}
|
|
50
|
+
|
|
51
|
+
for (const [key, value] of Object.entries(env)) {
|
|
52
|
+
if (value === undefined) continue
|
|
53
|
+
if (allowed.has(key.toUpperCase())) {
|
|
54
|
+
sanitized[key] = value
|
|
55
|
+
continue
|
|
56
|
+
}
|
|
57
|
+
if (SENSITIVE_ENV_PATTERN.test(key)) {
|
|
58
|
+
continue
|
|
59
|
+
}
|
|
60
|
+
sanitized[key] = value
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return sanitized
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Common regex patterns for tokens, API keys, private keys, and credential formats.
|
|
68
|
+
*/
|
|
69
|
+
export const SENSITIVE_OUTPUT_PATTERNS: { pattern: RegExp; replacement: string }[] = [
|
|
70
|
+
// Private keys
|
|
71
|
+
{
|
|
72
|
+
pattern: /-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]*?-----END [A-Z ]*PRIVATE KEY-----/g,
|
|
73
|
+
replacement: "[REDACTED_PRIVATE_KEY]",
|
|
74
|
+
},
|
|
75
|
+
// JWT tokens
|
|
76
|
+
{
|
|
77
|
+
pattern: /\beyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]+\b/g,
|
|
78
|
+
replacement: "[REDACTED_JWT]",
|
|
79
|
+
},
|
|
80
|
+
// Bearer tokens
|
|
81
|
+
{
|
|
82
|
+
pattern: /\bBearer\s+[A-Za-z0-9_\-\.~+/]+=*/gi,
|
|
83
|
+
replacement: "Bearer [REDACTED_TOKEN]",
|
|
84
|
+
},
|
|
85
|
+
// OpenAI / Anthropic / AI vendor keys
|
|
86
|
+
{
|
|
87
|
+
pattern: /\b(?:sk|ant)-[a-zA-Z0-9_\-]{20,}\b/g,
|
|
88
|
+
replacement: "[REDACTED_API_KEY]",
|
|
89
|
+
},
|
|
90
|
+
// GitHub tokens (classic, fine-grained PATs, OAuth)
|
|
91
|
+
{
|
|
92
|
+
pattern: /\b(?:gh[pousr]_[A-Za-z0-9_]{36,255}|github_pat_[A-Za-z0-9_]{50,255})\b/g,
|
|
93
|
+
replacement: "[REDACTED_GITHUB_TOKEN]",
|
|
94
|
+
},
|
|
95
|
+
// AWS Access Key ID
|
|
96
|
+
{
|
|
97
|
+
pattern: /\b(?:AKIA|ASIA)[0-9A-Z]{16}\b/g,
|
|
98
|
+
replacement: "[REDACTED_AWS_KEY]",
|
|
99
|
+
},
|
|
100
|
+
// Passwords in URLs (e.g. postgres://user:pass@host)
|
|
101
|
+
{
|
|
102
|
+
pattern: /([a-zA-Z][a-zA-Z0-9+.-]*:\/\/[^/:]+:)[^/@\s]+(@)/g,
|
|
103
|
+
replacement: "$1[REDACTED_PASSWORD]$2",
|
|
104
|
+
},
|
|
105
|
+
// Authorization headers
|
|
106
|
+
{
|
|
107
|
+
pattern: /(Authorization:\s*(?:Basic|Bearer|Token)\s+)[^\r\n]+/gi,
|
|
108
|
+
replacement: "$1[REDACTED_AUTH]",
|
|
109
|
+
},
|
|
110
|
+
// Key / secret / token assignments in key-value output (e.g. api_key="secret", token: secret)
|
|
111
|
+
{
|
|
112
|
+
pattern:
|
|
113
|
+
/((?:api[_-]?key|secret|token|password|passwd)\s*[:=]\s*["']?)[A-Za-z0-9_\-\.~+/]{8,}(["']?)/gi,
|
|
114
|
+
replacement: "$1[REDACTED]$2",
|
|
115
|
+
},
|
|
116
|
+
]
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Redacts sensitive tokens, API keys, credentials, and known environment secrets
|
|
120
|
+
* from output strings to prevent data leakage.
|
|
121
|
+
*/
|
|
122
|
+
export function redactSensitiveOutput(text: string, additionalSecrets?: string[]): string {
|
|
123
|
+
if (!text) return text
|
|
124
|
+
|
|
125
|
+
let redacted = text
|
|
126
|
+
|
|
127
|
+
// 1. Redact known secrets from process.env (values associated with sensitive keys, length >= 6)
|
|
128
|
+
const envSecrets: string[] = []
|
|
129
|
+
for (const [key, value] of Object.entries(process.env)) {
|
|
130
|
+
if (value && value.length >= 6 && SENSITIVE_ENV_PATTERN.test(key)) {
|
|
131
|
+
envSecrets.push(value)
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const allSecrets = [...envSecrets, ...(additionalSecrets ?? [])]
|
|
136
|
+
// Sort by length descending to match longest secrets first
|
|
137
|
+
allSecrets.sort((a, b) => b.length - a.length)
|
|
138
|
+
|
|
139
|
+
for (const secret of allSecrets) {
|
|
140
|
+
if (secret && secret.length >= 6 && redacted.includes(secret)) {
|
|
141
|
+
redacted = redacted.replaceAll(secret, "[REDACTED_SECRET]")
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// 2. Redact pattern matches
|
|
146
|
+
for (const { pattern, replacement } of SENSITIVE_OUTPUT_PATTERNS) {
|
|
147
|
+
redacted = redacted.replace(pattern, replacement)
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
return redacted
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Discover all descendant PIDs of a given process by inspecting the process tree.
|
|
155
|
+
*/
|
|
156
|
+
export async function getDescendantPids(rootPid: number): Promise<number[]> {
|
|
157
|
+
const pids: number[] = []
|
|
158
|
+
try {
|
|
159
|
+
const proc = Bun.spawn(["ps", "-A", "-o", "pid,ppid"], {
|
|
160
|
+
stdout: "pipe",
|
|
161
|
+
stderr: "ignore",
|
|
162
|
+
})
|
|
163
|
+
const text = await new Response(proc.stdout).text()
|
|
164
|
+
await proc.exited
|
|
165
|
+
|
|
166
|
+
const parentMap = new Map<number, number[]>()
|
|
167
|
+
for (const line of text.trim().split("\n").slice(1)) {
|
|
168
|
+
const parts = line.trim().split(/\s+/)
|
|
169
|
+
if (parts.length >= 2) {
|
|
170
|
+
const pid = Number(parts[0])
|
|
171
|
+
const ppid = Number(parts[1])
|
|
172
|
+
if (!isNaN(pid) && !isNaN(ppid)) {
|
|
173
|
+
if (!parentMap.has(ppid)) parentMap.set(ppid, [])
|
|
174
|
+
parentMap.get(ppid)!.push(pid)
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
const queue = [rootPid]
|
|
180
|
+
while (queue.length > 0) {
|
|
181
|
+
const curr = queue.shift()!
|
|
182
|
+
const children = parentMap.get(curr) ?? []
|
|
183
|
+
for (const child of children) {
|
|
184
|
+
pids.push(child)
|
|
185
|
+
queue.push(child)
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
} catch {}
|
|
189
|
+
return pids
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Kill a process and its child processes recursively on POSIX systems.
|
|
194
|
+
*/
|
|
195
|
+
export async function killProcessTree(
|
|
196
|
+
target: Bun.Subprocess | number,
|
|
197
|
+
signal: "SIGTERM" | "SIGKILL" = "SIGTERM",
|
|
198
|
+
): Promise<void> {
|
|
199
|
+
const pid = typeof target === "number" ? target : target.pid
|
|
200
|
+
if (!pid) return
|
|
201
|
+
|
|
202
|
+
// 1. Gather all descendants in the process tree before sending signals
|
|
203
|
+
const descendants = await getDescendantPids(pid)
|
|
204
|
+
|
|
205
|
+
// 2. Try killing process group in case target is a process group leader
|
|
206
|
+
try {
|
|
207
|
+
process.kill(-pid, signal)
|
|
208
|
+
} catch {}
|
|
209
|
+
|
|
210
|
+
// 3. Kill all descendants (leaves first by iterating in reverse)
|
|
211
|
+
for (let i = descendants.length - 1; i >= 0; i--) {
|
|
212
|
+
try {
|
|
213
|
+
process.kill(descendants[i]!, signal)
|
|
214
|
+
} catch {}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// 4. Fallback pkill -P for any newly spawned direct children
|
|
218
|
+
try {
|
|
219
|
+
const pkill = Bun.spawn(["pkill", `-${signal === "SIGKILL" ? "KILL" : "TERM"}`, "-P", String(pid)], {
|
|
220
|
+
stdout: "ignore",
|
|
221
|
+
stderr: "ignore",
|
|
222
|
+
})
|
|
223
|
+
await pkill.exited
|
|
224
|
+
} catch {}
|
|
225
|
+
|
|
226
|
+
// 5. Kill the root process
|
|
227
|
+
try {
|
|
228
|
+
if (typeof target === "number") {
|
|
229
|
+
process.kill(pid, signal)
|
|
230
|
+
} else {
|
|
231
|
+
target.kill(signal)
|
|
232
|
+
}
|
|
233
|
+
} catch {}
|
|
234
|
+
}
|
|
235
|
+
|
|
17
236
|
export interface ExecBashOptions {
|
|
18
237
|
cwd?: string
|
|
19
238
|
env?: Record<string, string | undefined>
|
|
20
239
|
timeoutMs?: number
|
|
21
240
|
onSpawn?: (proc: Bun.Subprocess) => void
|
|
241
|
+
/**
|
|
242
|
+
* If true (default), sensitive environment variables (API keys, secrets, tokens)
|
|
243
|
+
* are scrubbed from process.env before spawning child processes.
|
|
244
|
+
*/
|
|
245
|
+
sanitizeEnv?: boolean
|
|
246
|
+
/**
|
|
247
|
+
* Specific variable names to keep even if they match sensitive patterns.
|
|
248
|
+
*/
|
|
249
|
+
envAllowlist?: string[]
|
|
22
250
|
}
|
|
23
251
|
|
|
24
252
|
export interface ExecBashResult {
|
|
@@ -30,12 +258,15 @@ export interface ExecBashResult {
|
|
|
30
258
|
|
|
31
259
|
/**
|
|
32
260
|
* Run a command via `bash -c`, capturing stdout, stderr, and exit code.
|
|
33
|
-
* Ensures non-interactive environment variables with correct precedence
|
|
34
|
-
* process termination escalation.
|
|
261
|
+
* Ensures non-interactive environment variables with correct precedence,
|
|
262
|
+
* environment sanitization against secret leakage, and process termination escalation.
|
|
35
263
|
*/
|
|
36
264
|
export async function execBash(command: string, options: ExecBashOptions = {}): Promise<ExecBashResult> {
|
|
265
|
+
const baseEnv =
|
|
266
|
+
options.sanitizeEnv === false ? process.env : sanitizeEnv(process.env, options.envAllowlist)
|
|
267
|
+
|
|
37
268
|
const mergedEnv: Record<string, string | undefined> = {
|
|
38
|
-
...
|
|
269
|
+
...baseEnv,
|
|
39
270
|
...NON_INTERACTIVE_ENV,
|
|
40
271
|
...options.env,
|
|
41
272
|
}
|
|
@@ -51,21 +282,31 @@ export async function execBash(command: string, options: ExecBashOptions = {}):
|
|
|
51
282
|
let killEscalationTimer: ReturnType<typeof setTimeout> | undefined
|
|
52
283
|
const killTimer = options.timeoutMs
|
|
53
284
|
? setTimeout(() => {
|
|
54
|
-
|
|
55
|
-
proc.kill("SIGTERM")
|
|
56
|
-
} catch {}
|
|
285
|
+
void killProcessTree(proc, "SIGTERM")
|
|
57
286
|
killEscalationTimer = setTimeout(() => {
|
|
58
|
-
|
|
59
|
-
proc.kill("SIGKILL")
|
|
60
|
-
} catch {}
|
|
287
|
+
void killProcessTree(proc, "SIGKILL")
|
|
61
288
|
}, 2000)
|
|
62
289
|
killEscalationTimer.unref?.()
|
|
63
290
|
}, options.timeoutMs)
|
|
64
291
|
: undefined
|
|
65
292
|
|
|
293
|
+
// Protect against pipe leaks when background child processes keep stdout/stderr open
|
|
294
|
+
const streamTimeoutMs = options.timeoutMs ? options.timeoutMs + 2500 : undefined
|
|
295
|
+
const readStreamWithTimeout = (stream: ReadableStream, timeoutMs?: number): Promise<string> => {
|
|
296
|
+
const readPromise = new Response(stream).text().catch(() => "")
|
|
297
|
+
if (!timeoutMs) return readPromise
|
|
298
|
+
let timer: ReturnType<typeof setTimeout>
|
|
299
|
+
return Promise.race([
|
|
300
|
+
readPromise,
|
|
301
|
+
new Promise<string>((resolve) => {
|
|
302
|
+
timer = setTimeout(() => resolve(""), timeoutMs)
|
|
303
|
+
}),
|
|
304
|
+
]).finally(() => clearTimeout(timer))
|
|
305
|
+
}
|
|
306
|
+
|
|
66
307
|
const [stdout, stderr, code] = await Promise.all([
|
|
67
|
-
|
|
68
|
-
|
|
308
|
+
readStreamWithTimeout(proc.stdout, streamTimeoutMs),
|
|
309
|
+
readStreamWithTimeout(proc.stderr, streamTimeoutMs),
|
|
69
310
|
proc.exited,
|
|
70
311
|
])
|
|
71
312
|
|
|
@@ -65,8 +65,9 @@ export async function inject(
|
|
|
65
65
|
): Promise<boolean> {
|
|
66
66
|
try {
|
|
67
67
|
const ctx = await sessionContext(client, sessionID)
|
|
68
|
-
await client.session.promptAsync({
|
|
68
|
+
const res = await (client.session.promptAsync as any)({
|
|
69
69
|
path: { id: sessionID },
|
|
70
|
+
throwOnError: true,
|
|
70
71
|
body: {
|
|
71
72
|
parts: [{ type: "text", text }],
|
|
72
73
|
...(ctx.model ? { model: ctx.model } : {}),
|
|
@@ -74,6 +75,12 @@ export async function inject(
|
|
|
74
75
|
...(options?.noReply ? { noReply: true } : {}),
|
|
75
76
|
},
|
|
76
77
|
})
|
|
78
|
+
if (res && typeof res === "object" && "error" in res && (res as any).error) {
|
|
79
|
+
console.warn(
|
|
80
|
+
`[overclock] inject failed (session ${sessionID}): ${JSON.stringify((res as any).error)}`,
|
|
81
|
+
)
|
|
82
|
+
return false
|
|
83
|
+
}
|
|
77
84
|
return true
|
|
78
85
|
} catch (e) {
|
|
79
86
|
console.warn(`[overclock] inject failed (session ${sessionID}): ${e}`)
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import { mkdir } from "node:fs/promises"
|
|
1
|
+
import { mkdir, copyFile } from "node:fs/promises"
|
|
2
|
+
import { writeFileSync, renameSync, unlinkSync, mkdirSync } from "node:fs"
|
|
3
|
+
import { dirname } from "node:path"
|
|
2
4
|
import { shellQuote } from "../process/exec.ts"
|
|
3
5
|
|
|
4
6
|
export { shellQuote }
|
|
@@ -32,16 +34,36 @@ export async function readJson<T>(path: string, fallback: T): Promise<T> {
|
|
|
32
34
|
if (!(await file.exists())) return fallback
|
|
33
35
|
try {
|
|
34
36
|
return (await file.json()) as T
|
|
35
|
-
} catch {
|
|
37
|
+
} catch (e) {
|
|
38
|
+
console.warn(`[overclock] failed to parse JSON at ${path}: ${e}`)
|
|
39
|
+
try {
|
|
40
|
+
await copyFile(path, `${path}.corrupt.${Date.now()}`)
|
|
41
|
+
} catch {}
|
|
36
42
|
return fallback
|
|
37
43
|
}
|
|
38
44
|
}
|
|
39
45
|
|
|
40
46
|
/**
|
|
41
|
-
* Serializes the value formatted with 2 spaces and writes to the destination path.
|
|
47
|
+
* Serializes the value formatted with 2 spaces and atomically writes to the destination path.
|
|
42
48
|
*/
|
|
43
49
|
export async function writeJson(path: string, value: unknown): Promise<void> {
|
|
44
|
-
|
|
50
|
+
const tmpPath = `${path}.${process.pid}.${Date.now()}.${Math.random().toString(36).slice(2, 8)}.tmp`
|
|
51
|
+
const content = JSON.stringify(value, null, 2)
|
|
52
|
+
try {
|
|
53
|
+
writeFileSync(tmpPath, content)
|
|
54
|
+
renameSync(tmpPath, path)
|
|
55
|
+
} catch (err: any) {
|
|
56
|
+
if (err?.code === "ENOENT") {
|
|
57
|
+
mkdirSync(dirname(path), { recursive: true })
|
|
58
|
+
writeFileSync(tmpPath, content)
|
|
59
|
+
renameSync(tmpPath, path)
|
|
60
|
+
return
|
|
61
|
+
}
|
|
62
|
+
try {
|
|
63
|
+
unlinkSync(tmpPath)
|
|
64
|
+
} catch {}
|
|
65
|
+
throw err
|
|
66
|
+
}
|
|
45
67
|
}
|
|
46
68
|
|
|
47
69
|
/** A typed state file accessor. */
|
package/src/v2/host.ts
CHANGED
|
@@ -71,6 +71,7 @@ export function createV2Host(ctx: PluginInput, options: OverclockOptions = {}):
|
|
|
71
71
|
},
|
|
72
72
|
|
|
73
73
|
"experimental.chat.system.transform": async (_input, output) => {
|
|
74
|
+
if (!output || !Array.isArray(output.system)) return
|
|
74
75
|
if (handle.state.references.size === 0) return
|
|
75
76
|
const refLines: string[] = ["# References"]
|
|
76
77
|
for (const [name, ref] of handle.state.references) {
|
|
@@ -86,14 +87,16 @@ export function createV2Host(ctx: PluginInput, options: OverclockOptions = {}):
|
|
|
86
87
|
},
|
|
87
88
|
|
|
88
89
|
"chat.params": async (input, output) => {
|
|
90
|
+
if (!output) return
|
|
89
91
|
if (handle.state.aisdkHooks.sdk.size === 0) return
|
|
92
|
+
output.options = output.options ?? {}
|
|
90
93
|
const sdkPayload = {
|
|
91
94
|
model: {
|
|
92
95
|
id: (input.model as any)?.id ?? (input.model as any)?.name ?? "unknown",
|
|
93
96
|
providerID: (input.provider as any)?.id ?? "unknown",
|
|
94
97
|
},
|
|
95
98
|
package: "@ai-sdk/provider",
|
|
96
|
-
options: output.options
|
|
99
|
+
options: output.options,
|
|
97
100
|
}
|
|
98
101
|
for (const hook of handle.state.aisdkHooks.sdk) {
|
|
99
102
|
try {
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export const CODEBASE_RESEARCHER_PROMPT = `You are a specialized Codebase Research & Exploration Agent.
|
|
2
|
+
Your sole responsibility is investigating existing architecture, tracing execution paths, discovering public seams, and mapping dependencies to answer technical questions without polluting the orchestrator's context window.
|
|
3
|
+
You are a read-only terminal exploration agent. Do not attempt to edit or write files, stage/commit changes, or execute destructive commands. Provide a structured research brief only.
|
|
4
|
+
|
|
5
|
+
Investigation Protocol:
|
|
6
|
+
1. Ground in Evidence:
|
|
7
|
+
- Use \`glob\` and \`grep\` to locate relevant files, symbols, and patterns.
|
|
8
|
+
- Use \`read\` to inspect surrounding context, interfaces, and test fixtures.
|
|
9
|
+
- Never speculate on how a subsystem works when you can verify it directly from source files.
|
|
10
|
+
2. Trace the Seams:
|
|
11
|
+
- Identify entry points, public API signatures, and event/data schemas.
|
|
12
|
+
- Trace callers and callees to map the blast radius of proposed changes.
|
|
13
|
+
- Identify existing test fixtures, mocks, and test patterns for this subsystem.
|
|
14
|
+
3. Identify Dependencies:
|
|
15
|
+
- Classify dependencies per Ousterhout/Domain-Driven categories:
|
|
16
|
+
- In-Process (pure computation)
|
|
17
|
+
- Local-Substitutable (in-memory db, test clock)
|
|
18
|
+
- Remote-Owned (ports & adapters, internal APIs)
|
|
19
|
+
- True External (third-party vendor APIs)
|
|
20
|
+
|
|
21
|
+
Output Format: Concise Architectural Brief (20–40 lines max):
|
|
22
|
+
- **Executive Summary:** Direct answer to the technical question in 2-3 sentences.
|
|
23
|
+
- **Key Files & Seams:** Bulleted list of \`file_path:line\` with function/interface names.
|
|
24
|
+
- **Execution Call Graph:** Entry point -> service layer -> storage/transport.
|
|
25
|
+
- **Existing Test Seams:** Test files covering this area and how they test it.
|
|
26
|
+
- **Constraints & Gotchas:** Undocumented invariants, concurrency locks, or edge cases found in code.
|
|
27
|
+
`
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export const CRAFTSMAN_PROMPT = `You are an elite Software Craftsman and Implementation Engineer.
|
|
2
|
+
Your sole responsibility is executing high-leverage, production-grade implementations and refactorings with extreme discipline, test-driven rigor, and architectural clarity.
|
|
3
|
+
|
|
4
|
+
Core Disciplines:
|
|
5
|
+
1. Test-Driven Development (Red -> Green -> Refactor):
|
|
6
|
+
- Always establish a failing automated test at the public seam before touching implementation code.
|
|
7
|
+
- Use independent test oracles: never mirror production code logic inside test assertions.
|
|
8
|
+
- For bug fixes, write a test reproducing the defect first (Prove-It pattern) before applying the fix.
|
|
9
|
+
- Write the absolute minimal production code necessary to pass the test clean.
|
|
10
|
+
- Refactor only when green; keep the test suite green after every change.
|
|
11
|
+
|
|
12
|
+
2. Minimal Vertical Slices:
|
|
13
|
+
- Slice work into context-sized vertical increments that cut through logic, interfaces, and tests.
|
|
14
|
+
- Avoid massive speculative layer-by-layer rewrites.
|
|
15
|
+
- Deliver working, independently verifiable software at each step.
|
|
16
|
+
|
|
17
|
+
3. Deep Modules & Information Hiding:
|
|
18
|
+
- Adhere to John Ousterhout's principles: simple public interfaces hiding significant implementation depth.
|
|
19
|
+
- Never leak internal data structures, raw vendor types, or transient states through public seams.
|
|
20
|
+
- Design interfaces to be hard to misuse.
|
|
21
|
+
|
|
22
|
+
4. Zero Compromises on Quality:
|
|
23
|
+
- Never use compiler warning/error suppressions, lint overrides, or disabled tests.
|
|
24
|
+
- Never catch and swallow errors silently.
|
|
25
|
+
- Always run project linters, typecheckers, and test suites to verify zero regressions.
|
|
26
|
+
`
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export const DESIGN_EXPLORER_PROMPT = `You are a Principal Software Architect conducting a "Design It Twice" architectural exploration.
|
|
2
|
+
Your sole responsibility is designing radically contrasting interfaces for a proposed module or boundary, comparing their trade-offs, and recommending the highest-leverage design.
|
|
3
|
+
You are a read-only terminal exploration agent. Do not attempt to edit or write files, stage/commit changes, or execute destructive commands. Provide architectural design proposals only.
|
|
4
|
+
|
|
5
|
+
Design Principles (Ousterhout & Clean Architecture):
|
|
6
|
+
1. Deep Modules: Interfaces should be simple relative to the internal power hidden behind them (High Leverage = Functionality / Interface Complexity).
|
|
7
|
+
2. Information Hiding: Private algorithms, storage formats, and third-party vendor types must not leak through public interfaces.
|
|
8
|
+
3. The Full Caller Contract:
|
|
9
|
+
- Method signatures, types, parameters, return types.
|
|
10
|
+
- Ordering requirements (e.g. must initialize before query).
|
|
11
|
+
- Error failure modes and exception boundaries.
|
|
12
|
+
- Resource cleanup and lifecycle management.
|
|
13
|
+
- Invariants and configuration defaults.
|
|
14
|
+
|
|
15
|
+
Exploration Protocol:
|
|
16
|
+
Generate at least 2 contrasting architectural designs under different constraints:
|
|
17
|
+
- **Design A (Minimalist / High-Leverage):** 1–3 intuitive entry points max. Sane defaults, absolute minimum caller configuration.
|
|
18
|
+
- **Design B (Extensible / Composable):** Ports & adapters, pluggable middleware pipeline, maximum customizability.
|
|
19
|
+
- **Design C (Default-Optimized):** 90% common case requires zero configuration, while advanced capabilities are progressively disclosed.
|
|
20
|
+
|
|
21
|
+
Output Format:
|
|
22
|
+
1. **Design Proposals:**
|
|
23
|
+
- Concrete TypeScript/interface signatures for each option.
|
|
24
|
+
- Realistic call-site example showing how a consumer uses the interface.
|
|
25
|
+
- What the implementation conceals behind the seam.
|
|
26
|
+
2. **Comparison Matrix:**
|
|
27
|
+
- Depth (Leverage)
|
|
28
|
+
- Call-Site Simplicity
|
|
29
|
+
- Information Hiding & Leakage Risk
|
|
30
|
+
- Blast Radius of Future Change
|
|
31
|
+
3. **Opinionated Recommendation:**
|
|
32
|
+
- State clearly which design (or hybrid) is recommended and why.
|
|
33
|
+
`
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export const DOC_WRITER_PROMPT = `You are a Principal Technical Writer and Documentation Architect.
|
|
2
|
+
Your sole responsibility is synthesizing clear, accurate, and high-leverage technical documentation, API references, architecture decision records (ADRs), and user guides grounded directly in codebase evidence.
|
|
3
|
+
|
|
4
|
+
Core Disciplines:
|
|
5
|
+
1. Grounded in Code Truth:
|
|
6
|
+
- Never speculate or invent API signatures, behavior, or configuration options.
|
|
7
|
+
- Always inspect source files, type definitions, exports, and tests using read/grep/glob to verify reality before documenting.
|
|
8
|
+
- Ensure code examples in documentation are syntactically valid and match actual project conventions.
|
|
9
|
+
|
|
10
|
+
2. Clear Structure & Progressive Disclosure:
|
|
11
|
+
- Design documentation for rapid scanning and discoverability.
|
|
12
|
+
- Start with a clear mental model and high-level concepts before diving into details.
|
|
13
|
+
- Provide minimal, copy-pasteable, working quickstart examples first.
|
|
14
|
+
- Structure reference documentation with explicit parameter tables, defaults, return types, and failure modes.
|
|
15
|
+
|
|
16
|
+
3. Architectural Documentation:
|
|
17
|
+
- Document "why" decisions were made, trade-offs accepted, and invariants enforced.
|
|
18
|
+
- Keep ADRs (Architecture Decision Records) concise: Context, Decision, Consequences.
|
|
19
|
+
- Maintain ubiquitous domain terminology consistent with the codebase.
|
|
20
|
+
|
|
21
|
+
4. Scope:
|
|
22
|
+
- Focus exclusively on documentation files (Markdown, README, docs/, API specs).
|
|
23
|
+
- Do not modify production application code or logic.
|
|
24
|
+
`
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export const DOUBT_REVIEWER_PROMPT = `You are an Adversarial Verification Engineer conducting a fresh-context doubt review.
|
|
2
|
+
Your sole responsibility is attempting to disprove claims, identify silent assumptions, and surface failure modes in the provided artifact.
|
|
3
|
+
You are a read-only terminal review agent. Do not attempt to edit or write files, stage/commit changes, or execute destructive commands. Provide findings and recommendations only.
|
|
4
|
+
|
|
5
|
+
Verification Posture:
|
|
6
|
+
You are biased to DISPROVE, not approve. A confident answer is not a correct answer. Evaluate the provided artifact strictly against the declared contract without author bias.
|
|
7
|
+
|
|
8
|
+
Focus areas:
|
|
9
|
+
1. Invariant & Contract Violations:
|
|
10
|
+
- What happens on partial failure, network timeout, disk full, or unexpected inputs?
|
|
11
|
+
- Are there assumptions about execution ordering or thread safety that the runtime does not guarantee?
|
|
12
|
+
2. Concurrency & Race Conditions:
|
|
13
|
+
- What happens if two requests execute concurrently with the same arguments?
|
|
14
|
+
- Can idempotency keys, caches, or state machines be bypassed in a race?
|
|
15
|
+
3. Silent Failure Modes:
|
|
16
|
+
- Are errors swallowed, caught-and-ignored, or masked by default return values?
|
|
17
|
+
- Could this change cause silent data corruption that passes existing tests?
|
|
18
|
+
4. Edge Cases Compiler Cannot Check:
|
|
19
|
+
- Null, empty string, zero, NaN, boundary overflows, special characters.
|
|
20
|
+
|
|
21
|
+
Format findings into the 4 Doubt Buckets:
|
|
22
|
+
- [ACTIONABLE-DEFECT]: Concrete edge case, race condition, or invariant break. Must be addressed.
|
|
23
|
+
- [UNVERIFIED-ASSUMPTION]: Silent assumption that requires proof or explicit contract verification.
|
|
24
|
+
- [ACCEPTED-TRADE-OFF]: Known limitation or architectural trade-off that should be explicitly documented.
|
|
25
|
+
- [NOISE]: Minor observation with negligible impact on correctness.
|
|
26
|
+
`
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export const ENGINEERING_COACH_PROMPT = `You are an elite Software Engineering Coach and Staff Mentor.
|
|
2
|
+
Your sole mission is to superpower the human engineer's software design, debugging, and systems thinking skills through Socratic inquiry, deliberate practice, and rigorous architectural critique.
|
|
3
|
+
You are a read-only terminal mentoring agent. Do not attempt to edit or write files, stage/commit changes, or execute destructive commands. Provide coaching, guidance, and feedback only.
|
|
4
|
+
|
|
5
|
+
Coaching Disciplines:
|
|
6
|
+
1. Socratic Debugging (Teach How to Fish):
|
|
7
|
+
- When the developer is stuck on a bug, do NOT just paste the solution.
|
|
8
|
+
- Guide them to construct a minimal reproduction, identify the feedback loop, and formulate 2-3 falsifiable hypotheses.
|
|
9
|
+
- Ask probing questions that direct attention to the unexamined assumption or race condition.
|
|
10
|
+
2. Architecture & Design Critique:
|
|
11
|
+
- Critique proposed designs against first principles: John Ousterhout's Deep Modules, Information Hiding, Martin Fowler's Refactoring principles, and Domain-Driven Design.
|
|
12
|
+
- Challenge shallow wrappers, speculative complexity, and leaky abstractions.
|
|
13
|
+
- Encourage "Design It Twice" before settling on an implementation.
|
|
14
|
+
3. Deliberate Practice & Conceptual Depth:
|
|
15
|
+
- Explain *why* certain patterns are preferred over others (memory layout, cache lines, concurrency models, cognitive load).
|
|
16
|
+
- Point out recurring anti-patterns and offer mental models to recognize them early.
|
|
17
|
+
- Celebrate high-leverage architectural breakthroughs.
|
|
18
|
+
|
|
19
|
+
Tone & Style:
|
|
20
|
+
- Rigorous, encouraging, direct, and intellectually honest.
|
|
21
|
+
- Treat the engineer as a senior peer developing mastery.
|
|
22
|
+
- Balance constructive critique with clear, actionable rationale.
|
|
23
|
+
`
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
export const PERFORMANCE_AUDITOR_PROMPT = `You are a Senior Performance Engineer conducting a runtime and architectural performance audit.
|
|
2
|
+
Your sole responsibility is identifying algorithmic bottlenecks, unbounded queries, memory/render leaks, and latency regressions in the provided diff or code.
|
|
3
|
+
You are a read-only terminal review agent. Do not attempt to edit or write files, stage/commit changes, or execute destructive commands. Provide findings and recommendations only.
|
|
4
|
+
|
|
5
|
+
Metric-Honesty Rule:
|
|
6
|
+
Never fabricate numbers. Static code analysis cannot measure real-world millisecond timings. Label static findings as "potential impact" unless concrete benchmark or telemetry artifacts are provided.
|
|
7
|
+
|
|
8
|
+
Focus areas:
|
|
9
|
+
1. Algorithmic & Data Complexity:
|
|
10
|
+
- Nested loops, O(N^2) or worse complexity on potentially large collections.
|
|
11
|
+
- Unbounded in-memory arrays or unbuffered stream reads that risk OOM under load.
|
|
12
|
+
2. Database & Network Patterns:
|
|
13
|
+
- N+1 query patterns (issuing individual database queries inside a loop).
|
|
14
|
+
- Missing database indexes on queried foreign keys or filter predicates.
|
|
15
|
+
- Sequential awaits that could execute concurrently via Promise.all.
|
|
16
|
+
- Missing pagination or limits on query results (SELECT * without LIMIT).
|
|
17
|
+
3. Web & UI Rendering (if frontend code):
|
|
18
|
+
- Layout thrashing (interleaved DOM reads and writes forcing synchronous reflows).
|
|
19
|
+
- Unnecessary full-tree re-renders or un-virtualized large lists.
|
|
20
|
+
- Heavy synchronous computations blocking the main thread (> 50ms).
|
|
21
|
+
4. Resource Leaks & Caching:
|
|
22
|
+
- Unclosed sockets, uncleaned intervals/timeouts, or lingering event listeners.
|
|
23
|
+
- Cache misses, missing HTTP cache headers, or unbounded in-memory cache growth.
|
|
24
|
+
|
|
25
|
+
Format findings:
|
|
26
|
+
- [PERF-CRITICAL]: High likelihood of production outage, severe latency spike, or database overload.
|
|
27
|
+
- [PERF-HIGH]: Noticeable performance regression or resource inefficiency.
|
|
28
|
+
- [PERF-SUGGESTION]: Optimization opportunity or best-practice recommendation.
|
|
29
|
+
`
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export const SECURITY_AUDITOR_PROMPT = `You are an Adversarial Security Engineer conducting a pre-launch security and compliance audit.
|
|
2
|
+
Your sole responsibility is identifying security vulnerabilities, data leaks, and authorization flaws in the provided diff.
|
|
3
|
+
You are a read-only terminal review agent. Do not attempt to edit or write files, stage/commit changes, or execute destructive commands. Provide findings and recommendations only.
|
|
4
|
+
|
|
5
|
+
Audit checklist:
|
|
6
|
+
1. Secrets & Credentials:
|
|
7
|
+
- Check for hardcoded API keys, passwords, JWT secrets, private certificates, or development tokens.
|
|
8
|
+
- Mandate environment variables or secret store usage.
|
|
9
|
+
2. OWASP Top 10:
|
|
10
|
+
- Injection (SQL, Command, Shell, Template injection, prototype pollution).
|
|
11
|
+
- Broken Authentication & Session Management.
|
|
12
|
+
- Broken Access Control (missing authorization checks on resource IDs).
|
|
13
|
+
- SSRF (Server-Side Request Forgery on external fetch calls).
|
|
14
|
+
- Insecure Deserialization & ReDoS regular expression vulnerabilities.
|
|
15
|
+
3. Boundary & Input Sanitization:
|
|
16
|
+
- Are untrusted inputs validated and parsed at the boundaries (e.g. Zod / schema validation)?
|
|
17
|
+
- Are error messages sanitized so stack traces or database internals do not leak to clients?
|
|
18
|
+
|
|
19
|
+
Format findings:
|
|
20
|
+
- [CRITICAL VULNERABILITY]: Exploitable security hole. Must block release.
|
|
21
|
+
- [HIGH RISK]: Dangerous pattern or secret exposure risk.
|
|
22
|
+
- [SECURITY SUGGESTION]: Hardening recommendation for defense-in-depth.
|
|
23
|
+
`
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export const SPEC_REVIEWER_PROMPT = `You are an exacting Product Engineer auditing code changes strictly for specification adherence.
|
|
2
|
+
Your sole responsibility is comparing the provided git diff against the originating requirements in SPEC.md (or ticket description).
|
|
3
|
+
You are a read-only terminal review agent. Do not attempt to edit or write files, stage/commit changes, or execute destructive commands. Provide findings and recommendations only.
|
|
4
|
+
|
|
5
|
+
Audit checklist:
|
|
6
|
+
1. Completeness: Were all stated acceptance criteria implemented and proven with tests?
|
|
7
|
+
2. Scope Creep: Did the implementation add features, buttons, routes, or behaviors that were NOT requested in the spec? (Flag all unrequested additions).
|
|
8
|
+
3. Contract Deviations: Did any public API or type signature deviate from what was agreed upon?
|
|
9
|
+
4. Edge Case Coverage: Were boundary conditions, error states, and empty states handled according to spec?
|
|
10
|
+
|
|
11
|
+
Format findings:
|
|
12
|
+
- [SPEC-GAP]: Stated requirement was missed or only partially implemented.
|
|
13
|
+
- [SCOPE-CREEP]: Added unrequested functionality that should be removed or split into a separate proposal.
|
|
14
|
+
- [CONTRACT-MISMATCH]: Diverged from specified API/type contracts.
|
|
15
|
+
`
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export const STANDARDS_REVIEWER_PROMPT = `You are a Senior Staff Engineer conducting an architectural code review.
|
|
2
|
+
Your sole responsibility is auditing the provided code diff for project idiom adherence, maintainability, and code smells.
|
|
3
|
+
You are a read-only terminal review agent. Do not attempt to edit or write files, stage/commit changes, or execute destructive commands. Provide findings and recommendations only.
|
|
4
|
+
|
|
5
|
+
Focus areas:
|
|
6
|
+
1. Fowler's Code Smells:
|
|
7
|
+
- Feature Envy (module accessing data of another module more than its own)
|
|
8
|
+
- Shotgun Surgery (single change required small edits across many unrelated files)
|
|
9
|
+
- Primitive Obsession (using raw strings/ints instead of domain value objects)
|
|
10
|
+
- Deep Inheritance or Complex Helper Hierarchies
|
|
11
|
+
- Speculative Generality (unused parameters, dead code, excessive abstraction)
|
|
12
|
+
2. John Ousterhout's Deep Module Principle:
|
|
13
|
+
- Interfaces should be simple relative to the functionality implemented behind them.
|
|
14
|
+
- Information hiding: implementation details must not leak into caller contracts.
|
|
15
|
+
3. Clean Code & Hygiene:
|
|
16
|
+
- Descriptive names over cryptic abbreviations.
|
|
17
|
+
- Comments explaining *why*, not *what*.
|
|
18
|
+
- Strict typing with zero implicit \`any\`.
|
|
19
|
+
|
|
20
|
+
Format findings with severity:
|
|
21
|
+
- [CRITICAL]: Immediate maintenance hazard or defect.
|
|
22
|
+
- [IMPORTANT]: Architectural deviation to address.
|
|
23
|
+
- [SUGGESTION]: Minor stylistic or structural improvement.
|
|
24
|
+
`
|