pluidr 0.6.1 → 0.7.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/LICENSE +20 -20
- package/README.md +365 -357
- package/bin/pluidr.js +3 -3
- package/package.json +45 -45
- package/src/cli/commands/doctor.js +101 -99
- package/src/cli/commands/init.js +43 -43
- package/src/cli/commands/launch.js +46 -0
- package/src/cli/commands/uninstall.js +63 -67
- package/src/cli/commands/update.js +6 -22
- package/src/cli/index.js +57 -53
- package/src/cli/wizard/selectModelTier.js +40 -39
- package/src/core/agentPromptWriter.js +32 -32
- package/src/core/agentPromptWriter.test.js +56 -56
- package/src/core/backup.js +40 -38
- package/src/core/configBuilder.js +32 -32
- package/src/core/configBuilder.test.js +93 -47
- package/src/core/configWriter.js +10 -10
- package/src/core/identityHeader.js +8 -8
- package/src/core/paths.js +9 -9
- package/src/core/paths.test.js +21 -21
- package/src/core/pluginWriter.js +29 -29
- package/src/core/squeezeInstaller.js +161 -161
- package/src/core/squeezeInstaller.test.js +75 -75
- package/src/core/version.js +8 -0
- package/src/core/versionCheck.js +44 -0
- package/src/core/versionCheck.test.js +34 -0
- package/src/plugins/README.md +68 -68
- package/src/plugins/pluidr-squeeze.js +77 -77
- package/src/templates/agent-prompts/auditor.txt +20 -20
- package/src/templates/agent-prompts/coder.txt +87 -87
- package/src/templates/agent-prompts/compose-reporter.txt +55 -55
- package/src/templates/agent-prompts/composer.txt +430 -430
- package/src/templates/agent-prompts/debug-reporter.txt +65 -65
- package/src/templates/agent-prompts/debugger.txt +151 -151
- package/src/templates/agent-prompts/fixer.txt +66 -66
- package/src/templates/agent-prompts/hierarchy.txt +96 -96
- package/src/templates/agent-prompts/inspector.txt +79 -79
- package/src/templates/agent-prompts/patcher.txt +20 -20
- package/src/templates/agent-prompts/plan-checker.txt +45 -45
- package/src/templates/agent-prompts/plan-writer.txt +57 -57
- package/src/templates/agent-prompts/probe-reporter.txt +62 -62
- package/src/templates/agent-prompts/prober.txt +90 -90
- package/src/templates/agent-prompts/researcher.txt +48 -48
- package/src/templates/agent-prompts/reviewer.txt +57 -57
- package/src/templates/agent-prompts/tester.txt +66 -66
- package/src/templates/agent-prompts/tracer.txt +33 -33
- package/src/templates/model-defaults.json +73 -55
- package/src/templates/opencode.config.json +481 -481
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { execFileSync, execSync } from "node:child_process"
|
|
2
|
+
import { confirm, isCancel } from "@clack/prompts"
|
|
3
|
+
|
|
4
|
+
export function fetchLatestVersion() {
|
|
5
|
+
try {
|
|
6
|
+
if (process.platform === "win32") {
|
|
7
|
+
return execSync("npm view pluidr version", { stdio: "pipe" })
|
|
8
|
+
.toString()
|
|
9
|
+
.trim()
|
|
10
|
+
}
|
|
11
|
+
return execFileSync("npm", ["view", "pluidr", "version"], { stdio: "pipe" })
|
|
12
|
+
.toString()
|
|
13
|
+
.trim()
|
|
14
|
+
} catch {
|
|
15
|
+
return null
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export async function checkAndPromptUpdate(currentVersion) {
|
|
20
|
+
process.stdout.write("Checking for updates... ")
|
|
21
|
+
|
|
22
|
+
const latest = fetchLatestVersion()
|
|
23
|
+
if (!latest) {
|
|
24
|
+
console.log("⚠ Could not reach npm registry — skipping")
|
|
25
|
+
return false
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (latest === currentVersion) {
|
|
29
|
+
console.log(`✓ Up to date (${currentVersion})`)
|
|
30
|
+
return false
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
console.log(`⚠ pluidr ${latest} available (you have ${currentVersion})`)
|
|
34
|
+
|
|
35
|
+
const answer = await confirm({ message: "Update now?", initialValue: true })
|
|
36
|
+
if (isCancel(answer) || !answer) return false
|
|
37
|
+
|
|
38
|
+
if (process.platform === "win32") {
|
|
39
|
+
execSync("npm install -g pluidr", { stdio: "inherit" })
|
|
40
|
+
} else {
|
|
41
|
+
execFileSync("npm", ["install", "-g", "pluidr"], { stdio: "inherit" })
|
|
42
|
+
}
|
|
43
|
+
return true
|
|
44
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { describe, it } from "node:test"
|
|
2
|
+
import assert from "node:assert"
|
|
3
|
+
import { execFileSync, execSync } from "node:child_process"
|
|
4
|
+
import { fetchLatestVersion } from "./versionCheck.js"
|
|
5
|
+
|
|
6
|
+
describe("fetchLatestVersion", () => {
|
|
7
|
+
it("returns a string or null", () => {
|
|
8
|
+
// Either reaches npm registry (string) or fails gracefully (null)
|
|
9
|
+
const result = fetchLatestVersion()
|
|
10
|
+
assert.ok(result === null || typeof result === "string")
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
it("returns null when npm command throws", () => {
|
|
14
|
+
// Verify the try/catch in fetchLatestVersion swallows errors
|
|
15
|
+
let caught = null
|
|
16
|
+
try {
|
|
17
|
+
if (process.platform === "win32") {
|
|
18
|
+
execSync("npm view __nonexistent_pkg_xyz_pluidr__ version", { stdio: "pipe" })
|
|
19
|
+
} else {
|
|
20
|
+
execFileSync("npm", ["view", "__nonexistent_pkg_xyz_pluidr__", "version"], { stdio: "pipe" })
|
|
21
|
+
}
|
|
22
|
+
} catch (err) {
|
|
23
|
+
caught = err
|
|
24
|
+
}
|
|
25
|
+
// npm throws on unknown package — fetchLatestVersion handles this and returns null
|
|
26
|
+
assert.ok(caught instanceof Error, "npm should throw for unknown package")
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
it("uses execSync on Windows for npm, plain execFileSync on other platforms", () => {
|
|
30
|
+
// Confirm the platform guard evaluates correctly
|
|
31
|
+
const useSync = process.platform === "win32"
|
|
32
|
+
assert.strictEqual(typeof useSync, "boolean")
|
|
33
|
+
})
|
|
34
|
+
})
|
package/src/plugins/README.md
CHANGED
|
@@ -1,68 +1,68 @@
|
|
|
1
|
-
# Bundled plugins
|
|
2
|
-
|
|
3
|
-
This folder holds plugin source files that `pluidr init` copies into the
|
|
4
|
-
user's OpenCode plugin directory (`~/.config/opencode/plugins/`), giving
|
|
5
|
-
subagents cross-session context tools and command output filtering out of
|
|
6
|
-
the box.
|
|
7
|
-
|
|
8
|
-
## `pluidr-flow.js` — cross-session context
|
|
9
|
-
|
|
10
|
-
Implementation of the `SessionFlowPlugin`. Exposes three tools for reading
|
|
11
|
-
conversation history across related sessions (parent, sibling, or batch):
|
|
12
|
-
|
|
13
|
-
- `parent_session_messages` — read the parent session's full transcript
|
|
14
|
-
- `session_messages(sessionId)` — read any session by ID
|
|
15
|
-
- `session_messages_batch(sessionIds)` — read multiple sessions in one call
|
|
16
|
-
|
|
17
|
-
The output is a structured text dump with numbered messages, agent
|
|
18
|
-
attribution, and one-line tool-invocation summaries, separated by
|
|
19
|
-
`\n\n---\n\n`.
|
|
20
|
-
|
|
21
|
-
## `pluidr-squeeze.js` — command output filtering
|
|
22
|
-
|
|
23
|
-
Implementation of the `PluidrSqueezePlugin`. Hooks into `tool.execute.before`
|
|
24
|
-
to rewrite bash commands through the local `squeeze` binary (built on the `rtk`
|
|
25
|
-
engine). The binary filters, groups, truncates, and deduplicates command
|
|
26
|
-
output — saving 60-90% of tokens across all agents.
|
|
27
|
-
|
|
28
|
-
The plugin is a thin delegator: all rewrite logic lives in the engine binary.
|
|
29
|
-
It checks `PATH` first, then falls back to Pluidr's managed location at
|
|
30
|
-
`~/.config/opencode/bin/squeeze`. If the binary is not found, the plugin
|
|
31
|
-
gracefully disables itself with a warning.
|
|
32
|
-
|
|
33
|
-
`pluidr init` downloads the `squeeze` binary automatically during setup.
|
|
34
|
-
|
|
35
|
-
## Why `pluidr-flow` was extracted
|
|
36
|
-
|
|
37
|
-
Subagents (Coder, Tester, Reviewer, Inspector, Fixer, etc.) run in fresh
|
|
38
|
-
child sessions with no access to the parent orchestrator's conversation
|
|
39
|
-
history. When a parent agent dispatches a subagent via the `Task` tool, the
|
|
40
|
-
subagent cannot see what was discussed in the parent — which means it has
|
|
41
|
-
to ask the user to re-paste context, or guess. `parent_session_messages`
|
|
42
|
-
bridges that gap: the subagent can fetch the parent transcript on demand
|
|
43
|
-
and pick up where the parent left off.
|
|
44
|
-
|
|
45
|
-
## Why the identity plugin was dropped
|
|
46
|
-
|
|
47
|
-
The original `AgentSelfIdentityPlugin` injected agent identity via
|
|
48
|
-
`experimental.chat.*` hooks. Pluidr's 12 agent names are known at install
|
|
49
|
-
time, so we prepend a static identity header (`You are the "<name>" agent.`)
|
|
50
|
-
to every generated prompt file. This is KISS: no hook evaluation per
|
|
51
|
-
request, no dependency on undocumented experimental APIs, single source
|
|
52
|
-
of truth in `src/core/identityHeader.js`.
|
|
53
|
-
|
|
54
|
-
## Why the attribution tool was dropped
|
|
55
|
-
|
|
56
|
-
The original `AgentAttributionToolPlugin` was designed for a Retrospective
|
|
57
|
-
agent that captures post-session observations. Pluidr has no Retrospective
|
|
58
|
-
agent in its pipeline, so the tool would have no caller — YAGNI.
|
|
59
|
-
|
|
60
|
-
## How they are loaded
|
|
61
|
-
|
|
62
|
-
`pluidr init` copies both plugins into `~/.config/opencode/plugins/` and
|
|
63
|
-
writes a `package.json` declaring `@opencode-ai/plugin: ^1.17.9` as a
|
|
64
|
-
dependency. For `pluidr-squeeze`, it also downloads and extracts the `squeeze`
|
|
65
|
-
engine binary to `~/.config/opencode/bin/`. On OpenCode's first launch, the
|
|
66
|
-
bundled Bun runtime detects the `package.json` and runs `bun install`
|
|
67
|
-
automatically — no user action required. Once installed, both plugins are
|
|
68
|
-
available to every agent that has the appropriate permissions.
|
|
1
|
+
# Bundled plugins
|
|
2
|
+
|
|
3
|
+
This folder holds plugin source files that `pluidr init` copies into the
|
|
4
|
+
user's OpenCode plugin directory (`~/.config/opencode/plugins/`), giving
|
|
5
|
+
subagents cross-session context tools and command output filtering out of
|
|
6
|
+
the box.
|
|
7
|
+
|
|
8
|
+
## `pluidr-flow.js` — cross-session context
|
|
9
|
+
|
|
10
|
+
Implementation of the `SessionFlowPlugin`. Exposes three tools for reading
|
|
11
|
+
conversation history across related sessions (parent, sibling, or batch):
|
|
12
|
+
|
|
13
|
+
- `parent_session_messages` — read the parent session's full transcript
|
|
14
|
+
- `session_messages(sessionId)` — read any session by ID
|
|
15
|
+
- `session_messages_batch(sessionIds)` — read multiple sessions in one call
|
|
16
|
+
|
|
17
|
+
The output is a structured text dump with numbered messages, agent
|
|
18
|
+
attribution, and one-line tool-invocation summaries, separated by
|
|
19
|
+
`\n\n---\n\n`.
|
|
20
|
+
|
|
21
|
+
## `pluidr-squeeze.js` — command output filtering
|
|
22
|
+
|
|
23
|
+
Implementation of the `PluidrSqueezePlugin`. Hooks into `tool.execute.before`
|
|
24
|
+
to rewrite bash commands through the local `squeeze` binary (built on the `rtk`
|
|
25
|
+
engine). The binary filters, groups, truncates, and deduplicates command
|
|
26
|
+
output — saving 60-90% of tokens across all agents.
|
|
27
|
+
|
|
28
|
+
The plugin is a thin delegator: all rewrite logic lives in the engine binary.
|
|
29
|
+
It checks `PATH` first, then falls back to Pluidr's managed location at
|
|
30
|
+
`~/.config/opencode/bin/squeeze`. If the binary is not found, the plugin
|
|
31
|
+
gracefully disables itself with a warning.
|
|
32
|
+
|
|
33
|
+
`pluidr init` downloads the `squeeze` binary automatically during setup.
|
|
34
|
+
|
|
35
|
+
## Why `pluidr-flow` was extracted
|
|
36
|
+
|
|
37
|
+
Subagents (Coder, Tester, Reviewer, Inspector, Fixer, etc.) run in fresh
|
|
38
|
+
child sessions with no access to the parent orchestrator's conversation
|
|
39
|
+
history. When a parent agent dispatches a subagent via the `Task` tool, the
|
|
40
|
+
subagent cannot see what was discussed in the parent — which means it has
|
|
41
|
+
to ask the user to re-paste context, or guess. `parent_session_messages`
|
|
42
|
+
bridges that gap: the subagent can fetch the parent transcript on demand
|
|
43
|
+
and pick up where the parent left off.
|
|
44
|
+
|
|
45
|
+
## Why the identity plugin was dropped
|
|
46
|
+
|
|
47
|
+
The original `AgentSelfIdentityPlugin` injected agent identity via
|
|
48
|
+
`experimental.chat.*` hooks. Pluidr's 12 agent names are known at install
|
|
49
|
+
time, so we prepend a static identity header (`You are the "<name>" agent.`)
|
|
50
|
+
to every generated prompt file. This is KISS: no hook evaluation per
|
|
51
|
+
request, no dependency on undocumented experimental APIs, single source
|
|
52
|
+
of truth in `src/core/identityHeader.js`.
|
|
53
|
+
|
|
54
|
+
## Why the attribution tool was dropped
|
|
55
|
+
|
|
56
|
+
The original `AgentAttributionToolPlugin` was designed for a Retrospective
|
|
57
|
+
agent that captures post-session observations. Pluidr has no Retrospective
|
|
58
|
+
agent in its pipeline, so the tool would have no caller — YAGNI.
|
|
59
|
+
|
|
60
|
+
## How they are loaded
|
|
61
|
+
|
|
62
|
+
`pluidr init` copies both plugins into `~/.config/opencode/plugins/` and
|
|
63
|
+
writes a `package.json` declaring `@opencode-ai/plugin: ^1.17.9` as a
|
|
64
|
+
dependency. For `pluidr-squeeze`, it also downloads and extracts the `squeeze`
|
|
65
|
+
engine binary to `~/.config/opencode/bin/`. On OpenCode's first launch, the
|
|
66
|
+
bundled Bun runtime detects the `package.json` and runs `bun install`
|
|
67
|
+
automatically — no user action required. Once installed, both plugins are
|
|
68
|
+
available to every agent that has the appropriate permissions.
|
|
@@ -1,77 +1,77 @@
|
|
|
1
|
-
import { existsSync } from "node:fs"
|
|
2
|
-
import { homedir } from "node:os"
|
|
3
|
-
import { join } from "node:path"
|
|
4
|
-
|
|
5
|
-
const BIN_NAME = process.platform === "win32" ? "squeeze.exe" : "squeeze"
|
|
6
|
-
const SQUEEZE_BIN = join(homedir(), ".config", "opencode", "bin", BIN_NAME)
|
|
7
|
-
|
|
8
|
-
function normalise(p) {
|
|
9
|
-
return p.replace(/\\/g, "/")
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
// Quote a path if it contains spaces so the shell treats it as one token.
|
|
13
|
-
export function shellQuote(p) {
|
|
14
|
-
return p.includes(" ") ? `"${p}"` : p
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
// Exported for testing. When binPath is the managed full path (not "squeeze"
|
|
18
|
-
// on PATH), the binary may output "rtk <cmd>" or "squeeze <cmd>" depending on
|
|
19
|
-
// how it resolves its own name. Replace the leading token with the actual
|
|
20
|
-
// binPath (quoted if it contains spaces) so the shell can find it. When
|
|
21
|
-
// squeeze is on PATH, normalise any "rtk" prefix to "squeeze".
|
|
22
|
-
export function resolveRewritten(rewritten, binPath) {
|
|
23
|
-
const m = rewritten.match(/^(rtk|squeeze)(\s|$)/)
|
|
24
|
-
if (!m) return rewritten
|
|
25
|
-
if (binPath === "squeeze") {
|
|
26
|
-
// squeeze is on PATH — normalise any leading binary name to "squeeze"
|
|
27
|
-
return "squeeze" + rewritten.slice(m[1].length)
|
|
28
|
-
}
|
|
29
|
-
// managed path — replace leading binary name with (quoted) full path
|
|
30
|
-
return shellQuote(binPath) + rewritten.slice(m[1].length)
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
async function findBinary($) {
|
|
34
|
-
try {
|
|
35
|
-
if (process.platform === "win32") {
|
|
36
|
-
await $`where squeeze`.quiet()
|
|
37
|
-
} else {
|
|
38
|
-
await $`which squeeze`.quiet()
|
|
39
|
-
}
|
|
40
|
-
return "squeeze"
|
|
41
|
-
} catch {
|
|
42
|
-
if (existsSync(SQUEEZE_BIN)) {
|
|
43
|
-
return normalise(SQUEEZE_BIN)
|
|
44
|
-
}
|
|
45
|
-
return null
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export const PluidrSqueezePlugin = async ({ $ }) => {
|
|
50
|
-
const binPath = await findBinary($)
|
|
51
|
-
if (!binPath) {
|
|
52
|
-
console.warn("[squeeze] squeeze binary not found — plugin disabled")
|
|
53
|
-
return {}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
return {
|
|
57
|
-
"tool.execute.before": async (input, output) => {
|
|
58
|
-
const tool = String(input?.tool ?? "").toLowerCase()
|
|
59
|
-
if (tool !== "bash" && tool !== "shell") return
|
|
60
|
-
const args = output?.args
|
|
61
|
-
if (!args || typeof args !== "object") return
|
|
62
|
-
|
|
63
|
-
const command = args.command
|
|
64
|
-
if (typeof command !== "string" || !command) return
|
|
65
|
-
|
|
66
|
-
try {
|
|
67
|
-
const result = await $`${binPath} rewrite ${command}`.quiet().nothrow()
|
|
68
|
-
const rewritten = String(result.stdout).trim()
|
|
69
|
-
if (rewritten && rewritten !== command) {
|
|
70
|
-
args.command = resolveRewritten(rewritten, binPath)
|
|
71
|
-
}
|
|
72
|
-
} catch {
|
|
73
|
-
// rewrite failed — pass through unchanged
|
|
74
|
-
}
|
|
75
|
-
},
|
|
76
|
-
}
|
|
77
|
-
}
|
|
1
|
+
import { existsSync } from "node:fs"
|
|
2
|
+
import { homedir } from "node:os"
|
|
3
|
+
import { join } from "node:path"
|
|
4
|
+
|
|
5
|
+
const BIN_NAME = process.platform === "win32" ? "squeeze.exe" : "squeeze"
|
|
6
|
+
const SQUEEZE_BIN = join(homedir(), ".config", "opencode", "bin", BIN_NAME)
|
|
7
|
+
|
|
8
|
+
function normalise(p) {
|
|
9
|
+
return p.replace(/\\/g, "/")
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// Quote a path if it contains spaces so the shell treats it as one token.
|
|
13
|
+
export function shellQuote(p) {
|
|
14
|
+
return p.includes(" ") ? `"${p}"` : p
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Exported for testing. When binPath is the managed full path (not "squeeze"
|
|
18
|
+
// on PATH), the binary may output "rtk <cmd>" or "squeeze <cmd>" depending on
|
|
19
|
+
// how it resolves its own name. Replace the leading token with the actual
|
|
20
|
+
// binPath (quoted if it contains spaces) so the shell can find it. When
|
|
21
|
+
// squeeze is on PATH, normalise any "rtk" prefix to "squeeze".
|
|
22
|
+
export function resolveRewritten(rewritten, binPath) {
|
|
23
|
+
const m = rewritten.match(/^(rtk|squeeze)(\s|$)/)
|
|
24
|
+
if (!m) return rewritten
|
|
25
|
+
if (binPath === "squeeze") {
|
|
26
|
+
// squeeze is on PATH — normalise any leading binary name to "squeeze"
|
|
27
|
+
return "squeeze" + rewritten.slice(m[1].length)
|
|
28
|
+
}
|
|
29
|
+
// managed path — replace leading binary name with (quoted) full path
|
|
30
|
+
return shellQuote(binPath) + rewritten.slice(m[1].length)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async function findBinary($) {
|
|
34
|
+
try {
|
|
35
|
+
if (process.platform === "win32") {
|
|
36
|
+
await $`where squeeze`.quiet()
|
|
37
|
+
} else {
|
|
38
|
+
await $`which squeeze`.quiet()
|
|
39
|
+
}
|
|
40
|
+
return "squeeze"
|
|
41
|
+
} catch {
|
|
42
|
+
if (existsSync(SQUEEZE_BIN)) {
|
|
43
|
+
return normalise(SQUEEZE_BIN)
|
|
44
|
+
}
|
|
45
|
+
return null
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export const PluidrSqueezePlugin = async ({ $ }) => {
|
|
50
|
+
const binPath = await findBinary($)
|
|
51
|
+
if (!binPath) {
|
|
52
|
+
console.warn("[squeeze] squeeze binary not found — plugin disabled")
|
|
53
|
+
return {}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return {
|
|
57
|
+
"tool.execute.before": async (input, output) => {
|
|
58
|
+
const tool = String(input?.tool ?? "").toLowerCase()
|
|
59
|
+
if (tool !== "bash" && tool !== "shell") return
|
|
60
|
+
const args = output?.args
|
|
61
|
+
if (!args || typeof args !== "object") return
|
|
62
|
+
|
|
63
|
+
const command = args.command
|
|
64
|
+
if (typeof command !== "string" || !command) return
|
|
65
|
+
|
|
66
|
+
try {
|
|
67
|
+
const result = await $`${binPath} rewrite ${command}`.quiet().nothrow()
|
|
68
|
+
const rewritten = String(result.stdout).trim()
|
|
69
|
+
if (rewritten && rewritten !== command) {
|
|
70
|
+
args.command = resolveRewritten(rewritten, binPath)
|
|
71
|
+
}
|
|
72
|
+
} catch {
|
|
73
|
+
// rewrite failed — pass through unchanged
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
}
|
|
77
|
+
}
|
|
@@ -1,20 +1,20 @@
|
|
|
1
|
-
# Role: Auditor Subagent
|
|
2
|
-
|
|
3
|
-
You are the **Auditor** subagent for the **Prober** agent. You act as a strict validation gate checking if security patches have resolved the vulnerabilities and ensuring no over-engineering was introduced.
|
|
4
|
-
|
|
5
|
-
## Auditor MUST NOT
|
|
6
|
-
- Propose remedies, suggest code adjustments, or edit code.
|
|
7
|
-
|
|
8
|
-
## Auditor MAY ONLY
|
|
9
|
-
- Inspect modified codebase files and run test commands to verify vulnerability elimination.
|
|
10
|
-
- Perform a security regression review: ensure the applied patches did not introduce new vulnerability pathways (e.g., input bypasses or insecure error handling).
|
|
11
|
-
- Perform an over-engineering review (Ponytail audit lens).
|
|
12
|
-
|
|
13
|
-
## Ponytail Audit Lens (Bloat Analysis)
|
|
14
|
-
Analyze changes for cognitive overload, accidental complexity, or redundant logic. Compile a list of unrequested abstractions, boilerplate, or excessive lines.
|
|
15
|
-
|
|
16
|
-
## Output Format
|
|
17
|
-
Your output must consist ONLY of:
|
|
18
|
-
- **Verdict**: PASS or FAIL
|
|
19
|
-
- **Gap List**: Specific files/lines where vulnerabilities are still active or regression was detected (FAIL cases only).
|
|
20
|
-
- **BLOAT List**: List of over-engineered constructs found in the patches.
|
|
1
|
+
# Role: Auditor Subagent
|
|
2
|
+
|
|
3
|
+
You are the **Auditor** subagent for the **Prober** agent. You act as a strict validation gate checking if security patches have resolved the vulnerabilities and ensuring no over-engineering was introduced.
|
|
4
|
+
|
|
5
|
+
## Auditor MUST NOT
|
|
6
|
+
- Propose remedies, suggest code adjustments, or edit code.
|
|
7
|
+
|
|
8
|
+
## Auditor MAY ONLY
|
|
9
|
+
- Inspect modified codebase files and run test commands to verify vulnerability elimination.
|
|
10
|
+
- Perform a security regression review: ensure the applied patches did not introduce new vulnerability pathways (e.g., input bypasses or insecure error handling).
|
|
11
|
+
- Perform an over-engineering review (Ponytail audit lens).
|
|
12
|
+
|
|
13
|
+
## Ponytail Audit Lens (Bloat Analysis)
|
|
14
|
+
Analyze changes for cognitive overload, accidental complexity, or redundant logic. Compile a list of unrequested abstractions, boilerplate, or excessive lines.
|
|
15
|
+
|
|
16
|
+
## Output Format
|
|
17
|
+
Your output must consist ONLY of:
|
|
18
|
+
- **Verdict**: PASS or FAIL
|
|
19
|
+
- **Gap List**: Specific files/lines where vulnerabilities are still active or regression was detected (FAIL cases only).
|
|
20
|
+
- **BLOAT List**: List of over-engineered constructs found in the patches.
|
|
@@ -1,88 +1,88 @@
|
|
|
1
|
-
# Role: Coder Subagent
|
|
2
|
-
|
|
3
|
-
You implement tasks assigned by Composer. If a PRD is provided, follow it exactly. If no PRD is provided (e.g., during a direct-build phase for simple tasks), follow the user's original specification and the Explore findings provided in the task payload verbatim. You manage your own task tracking internally via `todowrite` — this is not a persisted document, it's your working checklist for the current session.
|
|
4
|
-
|
|
5
|
-
Refer to `hierarchy.txt` (loaded globally) for conflict resolution.
|
|
6
|
-
|
|
7
|
-
## Principles
|
|
8
|
-
|
|
9
|
-
**KISS**
|
|
10
|
-
- Choose the simplest implementation that satisfies the requirement.
|
|
11
|
-
- If a more complex approach is chosen, explain why in a comment.
|
|
12
|
-
|
|
13
|
-
**DRY**
|
|
14
|
-
- Before writing new logic, check if equivalent logic already exists.
|
|
15
|
-
- If duplication is unavoidable in this pass, flag it.
|
|
16
|
-
|
|
17
|
-
**Fail Fast / Defensive Programming**
|
|
18
|
-
- Validate all inputs at function/API boundaries.
|
|
19
|
-
- Never assume upstream data is valid — raise explicit errors.
|
|
20
|
-
|
|
21
|
-
**SOLID — Dependency Inversion**
|
|
22
|
-
- Depend on abstractions (interfaces, protocols) not concrete implementations,
|
|
23
|
-
especially for external services (DB, API clients).
|
|
24
|
-
|
|
25
|
-
**Clean Code**
|
|
26
|
-
- Meaningful names — no abbreviations unless domain-standard (e.g., `id`, `db`).
|
|
27
|
-
- Small functions — one function does one thing.
|
|
28
|
-
- No hidden side effects.
|
|
29
|
-
- Minimize comments — code should be self-explanatory; comment only "why", not "what".
|
|
30
|
-
|
|
31
|
-
**Single Level of Abstraction**
|
|
32
|
-
- A function should not mix high-level orchestration with low-level details
|
|
33
|
-
(e.g., business logic + raw SQL in the same function).
|
|
34
|
-
|
|
35
|
-
## Delegation rules
|
|
36
|
-
|
|
37
|
-
You have no `task` permission — you cannot invoke any other agent or
|
|
38
|
-
subagent. If implementation reveals a need for research (e.g., unclear
|
|
39
|
-
library behavior) or a requirement question, stop and report back to
|
|
40
|
-
Composer rather than guessing or trying to research it yourself outside
|
|
41
|
-
your given tools.
|
|
42
|
-
|
|
43
|
-
## Task tracking
|
|
44
|
-
|
|
45
|
-
- Use `todowrite` to break the assigned task(s) into a working checklist
|
|
46
|
-
before starting implementation.
|
|
47
|
-
- Update status as you progress. This is for session visibility, not a
|
|
48
|
-
deliverable — do not write it to a file.
|
|
49
|
-
|
|
50
|
-
## What you do NOT do
|
|
51
|
-
|
|
52
|
-
- You do not change the requirement — if the PRD task is ambiguous or
|
|
53
|
-
infeasible as written, stop and report back to Composer rather than
|
|
54
|
-
reinterpreting it.
|
|
55
|
-
- You do not produce documentation — that's Compose-Reporter's job.
|
|
56
|
-
|
|
57
|
-
## Output
|
|
58
|
-
|
|
59
|
-
- Code changes, with a brief note on any deviation from the assigned task (if any).
|
|
60
|
-
- Flag any duplicated logic found during implementation.
|
|
61
|
-
|
|
62
|
-
## Efficiency Constraints
|
|
63
|
-
|
|
64
|
-
**Decision Ladder**
|
|
65
|
-
Before writing any code, stop at the first rung that holds:
|
|
66
|
-
1. Does this need to be built at all? (YAGNI)
|
|
67
|
-
2. Does it already exist in this codebase? Reuse the helper, util, or pattern that's already here, don't re-write it.
|
|
68
|
-
3. Does the standard library already do this? Use it.
|
|
69
|
-
4. Does a native platform feature cover it? Use it.
|
|
70
|
-
5. Does an already-installed dependency solve it? Use it.
|
|
71
|
-
6. Can this be one line? Make it one line.
|
|
72
|
-
7. Only then: write the minimum code that works.
|
|
73
|
-
|
|
74
|
-
The ladder runs after you understand the problem: read the task and the code it touches, trace the real flow end to end, then climb.
|
|
75
|
-
|
|
76
|
-
**Never-Simplify Rules (Not Lazy About)**
|
|
77
|
-
- Understanding the problem: Trace the real flow before coding.
|
|
78
|
-
- Input validation at trust boundaries.
|
|
79
|
-
- Error handling that prevents data loss.
|
|
80
|
-
- Security and accessibility.
|
|
81
|
-
- Anything explicitly requested.
|
|
82
|
-
- No abstractions that weren't explicitly requested.
|
|
83
|
-
- No new dependency if it can be avoided.
|
|
84
|
-
- No boilerplate nobody asked for.
|
|
85
|
-
- Deletion over addition. Boring over clever. Fewest files possible.
|
|
86
|
-
|
|
87
|
-
**Simplification Comment Convention**
|
|
1
|
+
# Role: Coder Subagent
|
|
2
|
+
|
|
3
|
+
You implement tasks assigned by Composer. If a PRD is provided, follow it exactly. If no PRD is provided (e.g., during a direct-build phase for simple tasks), follow the user's original specification and the Explore findings provided in the task payload verbatim. You manage your own task tracking internally via `todowrite` — this is not a persisted document, it's your working checklist for the current session.
|
|
4
|
+
|
|
5
|
+
Refer to `hierarchy.txt` (loaded globally) for conflict resolution.
|
|
6
|
+
|
|
7
|
+
## Principles
|
|
8
|
+
|
|
9
|
+
**KISS**
|
|
10
|
+
- Choose the simplest implementation that satisfies the requirement.
|
|
11
|
+
- If a more complex approach is chosen, explain why in a comment.
|
|
12
|
+
|
|
13
|
+
**DRY**
|
|
14
|
+
- Before writing new logic, check if equivalent logic already exists.
|
|
15
|
+
- If duplication is unavoidable in this pass, flag it.
|
|
16
|
+
|
|
17
|
+
**Fail Fast / Defensive Programming**
|
|
18
|
+
- Validate all inputs at function/API boundaries.
|
|
19
|
+
- Never assume upstream data is valid — raise explicit errors.
|
|
20
|
+
|
|
21
|
+
**SOLID — Dependency Inversion**
|
|
22
|
+
- Depend on abstractions (interfaces, protocols) not concrete implementations,
|
|
23
|
+
especially for external services (DB, API clients).
|
|
24
|
+
|
|
25
|
+
**Clean Code**
|
|
26
|
+
- Meaningful names — no abbreviations unless domain-standard (e.g., `id`, `db`).
|
|
27
|
+
- Small functions — one function does one thing.
|
|
28
|
+
- No hidden side effects.
|
|
29
|
+
- Minimize comments — code should be self-explanatory; comment only "why", not "what".
|
|
30
|
+
|
|
31
|
+
**Single Level of Abstraction**
|
|
32
|
+
- A function should not mix high-level orchestration with low-level details
|
|
33
|
+
(e.g., business logic + raw SQL in the same function).
|
|
34
|
+
|
|
35
|
+
## Delegation rules
|
|
36
|
+
|
|
37
|
+
You have no `task` permission — you cannot invoke any other agent or
|
|
38
|
+
subagent. If implementation reveals a need for research (e.g., unclear
|
|
39
|
+
library behavior) or a requirement question, stop and report back to
|
|
40
|
+
Composer rather than guessing or trying to research it yourself outside
|
|
41
|
+
your given tools.
|
|
42
|
+
|
|
43
|
+
## Task tracking
|
|
44
|
+
|
|
45
|
+
- Use `todowrite` to break the assigned task(s) into a working checklist
|
|
46
|
+
before starting implementation.
|
|
47
|
+
- Update status as you progress. This is for session visibility, not a
|
|
48
|
+
deliverable — do not write it to a file.
|
|
49
|
+
|
|
50
|
+
## What you do NOT do
|
|
51
|
+
|
|
52
|
+
- You do not change the requirement — if the PRD task is ambiguous or
|
|
53
|
+
infeasible as written, stop and report back to Composer rather than
|
|
54
|
+
reinterpreting it.
|
|
55
|
+
- You do not produce documentation — that's Compose-Reporter's job.
|
|
56
|
+
|
|
57
|
+
## Output
|
|
58
|
+
|
|
59
|
+
- Code changes, with a brief note on any deviation from the assigned task (if any).
|
|
60
|
+
- Flag any duplicated logic found during implementation.
|
|
61
|
+
|
|
62
|
+
## Efficiency Constraints
|
|
63
|
+
|
|
64
|
+
**Decision Ladder**
|
|
65
|
+
Before writing any code, stop at the first rung that holds:
|
|
66
|
+
1. Does this need to be built at all? (YAGNI)
|
|
67
|
+
2. Does it already exist in this codebase? Reuse the helper, util, or pattern that's already here, don't re-write it.
|
|
68
|
+
3. Does the standard library already do this? Use it.
|
|
69
|
+
4. Does a native platform feature cover it? Use it.
|
|
70
|
+
5. Does an already-installed dependency solve it? Use it.
|
|
71
|
+
6. Can this be one line? Make it one line.
|
|
72
|
+
7. Only then: write the minimum code that works.
|
|
73
|
+
|
|
74
|
+
The ladder runs after you understand the problem: read the task and the code it touches, trace the real flow end to end, then climb.
|
|
75
|
+
|
|
76
|
+
**Never-Simplify Rules (Not Lazy About)**
|
|
77
|
+
- Understanding the problem: Trace the real flow before coding.
|
|
78
|
+
- Input validation at trust boundaries.
|
|
79
|
+
- Error handling that prevents data loss.
|
|
80
|
+
- Security and accessibility.
|
|
81
|
+
- Anything explicitly requested.
|
|
82
|
+
- No abstractions that weren't explicitly requested.
|
|
83
|
+
- No new dependency if it can be avoided.
|
|
84
|
+
- No boilerplate nobody asked for.
|
|
85
|
+
- Deletion over addition. Boring over clever. Fewest files possible.
|
|
86
|
+
|
|
87
|
+
**Simplification Comment Convention**
|
|
88
88
|
- Mark intentional simplifications with a `simplification:` comment. If the shortcut has a known ceiling (global lock, O(n²) scan, naive heuristic), the comment must name the ceiling and the upgrade path.
|