@lovrozagar/grunt 0.5.2 → 0.6.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/.agents/agents/grunt.md +2 -24
- package/.agents/agents/orchestrator.md +5 -50
- package/.agents/skills/ask/SKILL.md +5 -12
- package/.agents/skills/auto/SKILL.md +7 -12
- package/.agents/skills/browser/SKILL.md +4 -8
- package/.agents/skills/clasp/SKILL.md +11 -0
- package/.agents/skills/commit/SKILL.md +3 -1
- package/.agents/skills/commit-push/SKILL.md +2 -0
- package/.agents/skills/commit-push-deploy/SKILL.md +2 -0
- package/.agents/skills/commit-push-release/SKILL.md +2 -0
- package/.agents/skills/explain/SKILL.md +7 -13
- package/.agents/skills/google-workspace/SKILL.md +13 -0
- package/.agents/skills/handoff/SKILL.md +7 -11
- package/.agents/skills/implement-plan/SKILL.md +5 -109
- package/.agents/skills/listen/SKILL.md +15 -0
- package/.agents/skills/pickup/SKILL.md +6 -12
- package/.agents/skills/speak/SKILL.md +13 -0
- package/.agents/skills/tmp/SKILL.md +6 -10
- package/.agents/skills/write-plan/SKILL.md +5 -77
- package/.claude/agents/grunt.md +2 -26
- package/.claude/agents/orchestrator.md +12 -50
- package/.claude/skills/ask/SKILL.md +5 -12
- package/.claude/skills/auto/SKILL.md +7 -12
- package/.claude/skills/browser/SKILL.md +4 -8
- package/.claude/skills/clasp/SKILL.md +11 -0
- package/.claude/skills/commit/SKILL.md +3 -1
- package/.claude/skills/commit-push/SKILL.md +2 -0
- package/.claude/skills/commit-push-deploy/SKILL.md +2 -0
- package/.claude/skills/commit-push-release/SKILL.md +2 -0
- package/.claude/skills/explain/SKILL.md +7 -13
- package/.claude/skills/google-workspace/SKILL.md +13 -0
- package/.claude/skills/handoff/SKILL.md +7 -11
- package/.claude/skills/implement-plan/SKILL.md +5 -109
- package/.claude/skills/listen/SKILL.md +15 -0
- package/.claude/skills/pickup/SKILL.md +6 -12
- package/.claude/skills/speak/SKILL.md +13 -0
- package/.claude/skills/tmp/SKILL.md +6 -10
- package/.claude/skills/write-plan/SKILL.md +5 -77
- package/.codex/agents/grunt.toml +2 -26
- package/.codex/agents/orchestrator.toml +4 -50
- package/.grok/agents/grunt.md +2 -24
- package/.grok/agents/orchestrator.md +4 -48
- package/.grok/global-settings.toml +1 -3
- package/.grok/hooks/orchestrate-parent.js +190 -358
- package/.grok/skills/ask/SKILL.md +5 -12
- package/.grok/skills/auto/SKILL.md +7 -12
- package/.grok/skills/browser/SKILL.md +4 -8
- package/.grok/skills/clasp/SKILL.md +11 -0
- package/.grok/skills/commit/SKILL.md +3 -1
- package/.grok/skills/commit-push/SKILL.md +2 -0
- package/.grok/skills/commit-push-deploy/SKILL.md +2 -0
- package/.grok/skills/commit-push-release/SKILL.md +2 -0
- package/.grok/skills/explain/SKILL.md +7 -13
- package/.grok/skills/google-workspace/SKILL.md +13 -0
- package/.grok/skills/handoff/SKILL.md +7 -11
- package/.grok/skills/implement-plan/SKILL.md +5 -109
- package/.grok/skills/listen/SKILL.md +15 -0
- package/.grok/skills/pickup/SKILL.md +6 -12
- package/.grok/skills/speak/SKILL.md +13 -0
- package/.grok/skills/tmp/SKILL.md +6 -10
- package/.grok/skills/write-plan/SKILL.md +5 -77
- package/.rulesync/hooks.jsonc +1 -1
- package/.rulesync/mcp-policy.jsonc +0 -2
- package/.rulesync/reference/INDEX.md +30 -20
- package/.rulesync/reference/browser.md +13 -6
- package/.rulesync/reference/cascade.md +6 -86
- package/.rulesync/reference/clasp.md +21 -0
- package/.rulesync/reference/google-workspace.md +79 -0
- package/.rulesync/reference/hooks.md +7 -11
- package/.rulesync/reference/implementation-format.md +113 -0
- package/.rulesync/reference/law.md +5 -3
- package/.rulesync/reference/listen.md +80 -0
- package/.rulesync/reference/map.md +39 -36
- package/.rulesync/reference/output.md +3 -51
- package/.rulesync/reference/plan-format.md +4 -2
- package/.rulesync/reference/refs-map.md +12 -5
- package/.rulesync/reference/rtk.md +3 -2
- package/.rulesync/reference/scope.md +37 -0
- package/.rulesync/reference/setup.md +27 -0
- package/.rulesync/reference/skills-map.md +13 -12
- package/.rulesync/reference/speak.md +59 -0
- package/.rulesync/rules/CLAUDE.md +3 -49
- package/.rulesync/rules/overview.md +9 -47
- package/.rulesync/skills/ask/SKILL.md +5 -12
- package/.rulesync/skills/auto/SKILL.md +5 -12
- package/.rulesync/skills/browser/SKILL.md +4 -8
- package/.rulesync/skills/clasp/SKILL.md +9 -0
- package/.rulesync/skills/commit/SKILL.md +3 -1
- package/.rulesync/skills/commit-push/SKILL.md +2 -0
- package/.rulesync/skills/commit-push-deploy/SKILL.md +2 -0
- package/.rulesync/skills/commit-push-release/SKILL.md +2 -0
- package/.rulesync/skills/explain/SKILL.md +7 -14
- package/.rulesync/skills/google-workspace/SKILL.md +11 -0
- package/.rulesync/skills/handoff/SKILL.md +7 -11
- package/.rulesync/skills/implement-plan/SKILL.md +5 -119
- package/.rulesync/skills/listen/SKILL.md +13 -0
- package/.rulesync/skills/pickup/SKILL.md +6 -12
- package/.rulesync/skills/speak/SKILL.md +13 -0
- package/.rulesync/skills/tmp/SKILL.md +6 -10
- package/.rulesync/skills/write-plan/SKILL.md +5 -84
- package/.rulesync/subagents/grunt.md +2 -24
- package/.rulesync/subagents/orchestrator.md +14 -59
- package/AGENTS.md +9 -47
- package/CHANGELOG.md +56 -0
- package/CLAUDE.md +1 -49
- package/README.md +88 -80
- package/cli/grunt.mjs +18 -2
- package/cli/grunt.test.ts +33 -0
- package/cli/init.mjs +103 -10
- package/cli/init.test.ts +147 -35
- package/cli/prompt.mjs +8 -0
- package/cli/prompt.test.ts +14 -0
- package/package.json +7 -2
- package/scripts/browser.mjs +98 -5
- package/scripts/doctor.mjs +82 -1
- package/scripts/emit-gemini.mjs +1 -1
- package/scripts/emit-mcp-policy.mjs +1 -1
- package/scripts/gate-fat-tools.mjs +223 -173
- package/scripts/google-workspace.mjs +713 -0
- package/scripts/grunt-job.mjs +453 -69
- package/scripts/listen.mjs +829 -0
- package/scripts/parse-need.mjs +21 -2
- package/scripts/persist-implementation.mjs +278 -0
- package/scripts/scrub-spawn-prompt.mjs +3 -50
- package/scripts/setup.mjs +746 -0
- package/scripts/speak.mjs +291 -0
- package/.agents/agents/implementer.md +0 -32
- package/.agents/agents/thinker.md +0 -29
- package/.agents/skills/cascade/SKILL.md +0 -28
- package/.agents/skills/parent/SKILL.md +0 -6
- package/.agents/skills/solo/SKILL.md +0 -25
- package/.claude/agents/implementer.md +0 -37
- package/.claude/agents/thinker.md +0 -36
- package/.claude/skills/cascade/SKILL.md +0 -28
- package/.claude/skills/parent/SKILL.md +0 -6
- package/.claude/skills/solo/SKILL.md +0 -25
- package/.codex/agents/implementer.toml +0 -26
- package/.codex/agents/thinker.toml +0 -26
- package/.grok/agents/implementer.md +0 -27
- package/.grok/agents/thinker.md +0 -27
- package/.grok/parent.md +0 -1
- package/.grok/roles/implementer.toml +0 -5
- package/.grok/roles/thinker.toml +0 -5
- package/.grok/skills/cascade/SKILL.md +0 -28
- package/.grok/skills/parent/SKILL.md +0 -6
- package/.grok/skills/solo/SKILL.md +0 -25
- package/.rulesync/grunt.config.jsonc +0 -7
- package/.rulesync/skills/cascade/SKILL.md +0 -28
- package/.rulesync/skills/parent/SKILL.md +0 -6
- package/.rulesync/skills/solo/SKILL.md +0 -25
- package/.rulesync/subagents/implementer.md +0 -49
- package/.rulesync/subagents/thinker.md +0 -49
- package/scripts/grunt-config.mjs +0 -50
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/** Text-to-speech (output only). Providers: elevenlabs, openai. */
|
|
3
|
+
import { spawnSync } from "node:child_process";
|
|
4
|
+
import fs from "node:fs";
|
|
5
|
+
import os from "node:os";
|
|
6
|
+
import path from "node:path";
|
|
7
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
8
|
+
|
|
9
|
+
export const DEFAULT_ELEVEN_VOICE = "JBFqnCBsd6RMkjVDRZzb";
|
|
10
|
+
export const DEFAULT_ELEVEN_MODEL = "eleven_multilingual_v2";
|
|
11
|
+
export const DEFAULT_OPENAI_VOICE = "coral";
|
|
12
|
+
export const DEFAULT_OPENAI_MODEL = "gpt-4o-mini-tts";
|
|
13
|
+
export const OPENAI_VOICES = [
|
|
14
|
+
"alloy",
|
|
15
|
+
"ash",
|
|
16
|
+
"ballad",
|
|
17
|
+
"coral",
|
|
18
|
+
"echo",
|
|
19
|
+
"fable",
|
|
20
|
+
"nova",
|
|
21
|
+
"onyx",
|
|
22
|
+
"sage",
|
|
23
|
+
"shimmer",
|
|
24
|
+
];
|
|
25
|
+
export const USAGE =
|
|
26
|
+
"usage: speak whoami | voices | say --text T [--provider elevenlabs|openai] [--voice ID] [--out path] [--play]";
|
|
27
|
+
const ELEVEN_API = "https://api.elevenlabs.io/v1";
|
|
28
|
+
const OPENAI_API = "https://api.openai.com/v1";
|
|
29
|
+
export const SETUP = "node scripts/setup.mjs speak";
|
|
30
|
+
export const NEED_KEY =
|
|
31
|
+
"missing ELEVENLABS_API_KEY or OPENAI_API_KEY (or ~/.grunt/speak.json). setup: node scripts/setup.mjs speak";
|
|
32
|
+
export const NEED_ELEVEN =
|
|
33
|
+
"missing ELEVENLABS_API_KEY (or ~/.grunt/speak.json elevenlabs.apiKey). setup: node scripts/setup.mjs speak";
|
|
34
|
+
export const NEED_OPENAI =
|
|
35
|
+
"missing OPENAI_API_KEY (or ~/.grunt/speak.json openai.apiKey). setup: node scripts/setup.mjs speak";
|
|
36
|
+
|
|
37
|
+
export function formatHttpError(status, body, provider) {
|
|
38
|
+
const n = Number(status);
|
|
39
|
+
const raw = String(body || "");
|
|
40
|
+
if (/missing_permissions/i.test(raw)) {
|
|
41
|
+
return `${provider} key present but missing permission (${n || status}). setup: ${SETUP}`;
|
|
42
|
+
}
|
|
43
|
+
const auth =
|
|
44
|
+
n === 401 ||
|
|
45
|
+
n === 403 ||
|
|
46
|
+
/unauthorized|invalid.?api.?key|authentication/i.test(raw);
|
|
47
|
+
if (auth) {
|
|
48
|
+
return `${provider} key missing or rejected (${n || status}). setup: ${SETUP}`;
|
|
49
|
+
}
|
|
50
|
+
return `${status} ${raw.slice(0, 200)}`.trim();
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function parseArgv(argv) {
|
|
54
|
+
const out = { _: [], flags: {} };
|
|
55
|
+
const args = Array.isArray(argv) ? argv : [];
|
|
56
|
+
for (let i = 0; i < args.length; i++) {
|
|
57
|
+
const a = args[i];
|
|
58
|
+
if (a === "--") {
|
|
59
|
+
out._.push(...args.slice(i + 1));
|
|
60
|
+
break;
|
|
61
|
+
}
|
|
62
|
+
if (a.startsWith("--") && a.length > 2) {
|
|
63
|
+
const key = a.slice(2);
|
|
64
|
+
const nxt = args[i + 1];
|
|
65
|
+
if (nxt && !nxt.startsWith("--")) {
|
|
66
|
+
out.flags[key] = nxt;
|
|
67
|
+
i += 1;
|
|
68
|
+
} else out.flags[key] = "1";
|
|
69
|
+
} else out._.push(a);
|
|
70
|
+
}
|
|
71
|
+
return out;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function readJson(p) {
|
|
75
|
+
try {
|
|
76
|
+
const j = JSON.parse(fs.readFileSync(p, "utf8"));
|
|
77
|
+
if (j && typeof j === "object" && !Array.isArray(j)) return j;
|
|
78
|
+
} catch {
|
|
79
|
+
/* none */
|
|
80
|
+
}
|
|
81
|
+
return {};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function str(v, fallback = "") {
|
|
85
|
+
const s = String(v ?? "").trim();
|
|
86
|
+
return s || fallback;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export function loadCfg({ env = process.env, home = os.homedir() } = {}) {
|
|
90
|
+
const filePath = path.join(home, ".grunt", "speak.json");
|
|
91
|
+
const file = readJson(filePath);
|
|
92
|
+
const eleven = file.elevenlabs && typeof file.elevenlabs === "object" ? file.elevenlabs : {};
|
|
93
|
+
const openai = file.openai && typeof file.openai === "object" ? file.openai : {};
|
|
94
|
+
return {
|
|
95
|
+
filePath,
|
|
96
|
+
providerPref: str(env.SPEAK_PROVIDER || file.provider).toLowerCase(),
|
|
97
|
+
elevenlabs: {
|
|
98
|
+
apiKey: str(env.ELEVENLABS_API_KEY || eleven.apiKey || file.apiKey),
|
|
99
|
+
voiceId: str(env.ELEVENLABS_VOICE_ID || eleven.voiceId || file.voiceId, DEFAULT_ELEVEN_VOICE),
|
|
100
|
+
modelId: str(env.ELEVENLABS_MODEL_ID || eleven.modelId || file.modelId, DEFAULT_ELEVEN_MODEL),
|
|
101
|
+
},
|
|
102
|
+
openai: {
|
|
103
|
+
apiKey: str(env.OPENAI_API_KEY || openai.apiKey),
|
|
104
|
+
voice: str(env.OPENAI_TTS_VOICE || openai.voice, DEFAULT_OPENAI_VOICE),
|
|
105
|
+
model: str(env.OPENAI_TTS_MODEL || openai.model, DEFAULT_OPENAI_MODEL),
|
|
106
|
+
},
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export function resolveProvider(cfg, flagProvider) {
|
|
111
|
+
const want = str(flagProvider || (cfg && cfg.providerPref)).toLowerCase();
|
|
112
|
+
if (want && want !== "elevenlabs" && want !== "openai") {
|
|
113
|
+
throw new Error("provider must be elevenlabs or openai");
|
|
114
|
+
}
|
|
115
|
+
if (want === "elevenlabs") {
|
|
116
|
+
if (!cfg?.elevenlabs?.apiKey) throw new Error(NEED_ELEVEN);
|
|
117
|
+
return "elevenlabs";
|
|
118
|
+
}
|
|
119
|
+
if (want === "openai") {
|
|
120
|
+
if (!cfg?.openai?.apiKey) throw new Error(NEED_OPENAI);
|
|
121
|
+
return "openai";
|
|
122
|
+
}
|
|
123
|
+
if (cfg?.elevenlabs?.apiKey) return "elevenlabs";
|
|
124
|
+
if (cfg?.openai?.apiKey) return "openai";
|
|
125
|
+
throw new Error(NEED_KEY);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
async function apiFetch(url, { method = "GET", headers, body, raw, fetchFn } = {}) {
|
|
129
|
+
const fn = fetchFn || globalThis.fetch;
|
|
130
|
+
if (typeof fn !== "function") throw new Error("fetch is not available");
|
|
131
|
+
const res = await fn(url, {
|
|
132
|
+
method,
|
|
133
|
+
headers,
|
|
134
|
+
body: body ? JSON.stringify(body) : undefined,
|
|
135
|
+
});
|
|
136
|
+
if (!res || !res.ok) {
|
|
137
|
+
const status = res && res.status != null ? res.status : "err";
|
|
138
|
+
let t = "";
|
|
139
|
+
try {
|
|
140
|
+
t = res && typeof res.text === "function" ? await res.text() : "";
|
|
141
|
+
} catch {
|
|
142
|
+
/* none */
|
|
143
|
+
}
|
|
144
|
+
const provider = String(url || "").includes("elevenlabs") ? "elevenlabs" : "openai";
|
|
145
|
+
throw new Error(formatHttpError(status, t, provider));
|
|
146
|
+
}
|
|
147
|
+
if (raw) {
|
|
148
|
+
if (typeof res.arrayBuffer === "function") return Buffer.from(await res.arrayBuffer());
|
|
149
|
+
if (Buffer.isBuffer(res.body)) return res.body;
|
|
150
|
+
return Buffer.from(res.body || []);
|
|
151
|
+
}
|
|
152
|
+
if (typeof res.json === "function") return res.json();
|
|
153
|
+
return {};
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export async function whoami({ provider, cfg, fetchFn } = {}) {
|
|
157
|
+
const p = resolveProvider(cfg, provider);
|
|
158
|
+
if (p === "elevenlabs") {
|
|
159
|
+
try {
|
|
160
|
+
const u = await apiFetch(`${ELEVEN_API}/user`, {
|
|
161
|
+
headers: { "xi-api-key": cfg.elevenlabs.apiKey },
|
|
162
|
+
fetchFn,
|
|
163
|
+
});
|
|
164
|
+
const email = u && u.email ? u.email : "ok";
|
|
165
|
+
const tier = u && u.subscription && u.subscription.tier ? u.subscription.tier : "-";
|
|
166
|
+
return `elevenlabs ${email} tier=${tier}`;
|
|
167
|
+
} catch (e) {
|
|
168
|
+
const msg = String(e && e.message ? e.message : e);
|
|
169
|
+
if (/missing permission/i.test(msg)) {
|
|
170
|
+
return "elevenlabs ok (scoped key; whoami needs user_read). voices/say still work";
|
|
171
|
+
}
|
|
172
|
+
throw e;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
await apiFetch(`${OPENAI_API}/models`, {
|
|
176
|
+
headers: { Authorization: `Bearer ${cfg.openai.apiKey}` },
|
|
177
|
+
fetchFn,
|
|
178
|
+
});
|
|
179
|
+
return "openai ok";
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
export async function voices({ provider, cfg, fetchFn } = {}) {
|
|
183
|
+
const p = resolveProvider(cfg, provider);
|
|
184
|
+
if (p === "openai") return OPENAI_VOICES.join("\n");
|
|
185
|
+
const j = await apiFetch(`${ELEVEN_API}/voices`, {
|
|
186
|
+
headers: { "xi-api-key": cfg.elevenlabs.apiKey },
|
|
187
|
+
fetchFn,
|
|
188
|
+
});
|
|
189
|
+
const list = Array.isArray(j?.voices) ? j.voices : [];
|
|
190
|
+
return list.map((v) => `${v.voice_id} ${v.name}`).join("\n");
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
function playPath(dest) {
|
|
194
|
+
const bin = process.platform === "darwin" ? "afplay" : "ffplay";
|
|
195
|
+
const args = process.platform === "darwin" ? [dest] : ["-nodisp", "-autoexit", dest];
|
|
196
|
+
spawnSync(bin, args, { stdio: "ignore" });
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
export async function say({
|
|
200
|
+
text,
|
|
201
|
+
voice,
|
|
202
|
+
out,
|
|
203
|
+
play,
|
|
204
|
+
provider,
|
|
205
|
+
cfg,
|
|
206
|
+
cwd = process.cwd(),
|
|
207
|
+
fetchFn,
|
|
208
|
+
} = {}) {
|
|
209
|
+
if (!str(text)) throw new Error("say needs --text");
|
|
210
|
+
const p = resolveProvider(cfg, provider);
|
|
211
|
+
let buf;
|
|
212
|
+
if (p === "elevenlabs") {
|
|
213
|
+
const id = str(voice, cfg.elevenlabs.voiceId);
|
|
214
|
+
buf = await apiFetch(
|
|
215
|
+
`${ELEVEN_API}/text-to-speech/${encodeURIComponent(id)}?output_format=mp3_44100_128`,
|
|
216
|
+
{
|
|
217
|
+
method: "POST",
|
|
218
|
+
headers: {
|
|
219
|
+
"xi-api-key": cfg.elevenlabs.apiKey,
|
|
220
|
+
"Content-Type": "application/json",
|
|
221
|
+
},
|
|
222
|
+
body: { text: str(text), model_id: cfg.elevenlabs.modelId },
|
|
223
|
+
raw: true,
|
|
224
|
+
fetchFn,
|
|
225
|
+
},
|
|
226
|
+
);
|
|
227
|
+
} else {
|
|
228
|
+
const v = str(voice, cfg.openai.voice);
|
|
229
|
+
buf = await apiFetch(`${OPENAI_API}/audio/speech`, {
|
|
230
|
+
method: "POST",
|
|
231
|
+
headers: {
|
|
232
|
+
Authorization: `Bearer ${cfg.openai.apiKey}`,
|
|
233
|
+
"Content-Type": "application/json",
|
|
234
|
+
},
|
|
235
|
+
body: { model: cfg.openai.model, input: str(text), voice: v },
|
|
236
|
+
raw: true,
|
|
237
|
+
fetchFn,
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
const dest = str(out) || path.join(cwd, ".tmp/grunt/speak", `say-${Date.now()}.mp3`);
|
|
241
|
+
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
242
|
+
fs.writeFileSync(dest, buf);
|
|
243
|
+
if (play === true || play === "true" || play === "1") playPath(dest);
|
|
244
|
+
return dest;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
export async function main(argv = process.argv.slice(2), opts = {}) {
|
|
248
|
+
const { _, flags } = parseArgv(argv);
|
|
249
|
+
const env = opts.env || process.env;
|
|
250
|
+
const home = opts.home || os.homedir();
|
|
251
|
+
const cwd = opts.cwd || process.cwd();
|
|
252
|
+
const fetchFn = opts.fetchFn || globalThis.fetch;
|
|
253
|
+
const log = opts.log || console;
|
|
254
|
+
const cfg = loadCfg({ env, home });
|
|
255
|
+
const verb = String(_[0] || "").toLowerCase();
|
|
256
|
+
try {
|
|
257
|
+
if (verb === "whoami") {
|
|
258
|
+
log.log(await whoami({ provider: flags.provider, cfg, fetchFn }));
|
|
259
|
+
return 0;
|
|
260
|
+
}
|
|
261
|
+
if (verb === "voices") {
|
|
262
|
+
log.log(await voices({ provider: flags.provider, cfg, fetchFn }));
|
|
263
|
+
return 0;
|
|
264
|
+
}
|
|
265
|
+
if (verb === "say") {
|
|
266
|
+
const dest = await say({
|
|
267
|
+
text: flags.text,
|
|
268
|
+
voice: flags.voice,
|
|
269
|
+
out: flags.out,
|
|
270
|
+
play: flags.play,
|
|
271
|
+
provider: flags.provider,
|
|
272
|
+
cfg,
|
|
273
|
+
cwd,
|
|
274
|
+
fetchFn,
|
|
275
|
+
});
|
|
276
|
+
log.log(dest);
|
|
277
|
+
return 0;
|
|
278
|
+
}
|
|
279
|
+
log.error(USAGE);
|
|
280
|
+
return 1;
|
|
281
|
+
} catch (e) {
|
|
282
|
+
log.error(String(e && e.message ? e.message : e));
|
|
283
|
+
return 1;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
const thisFile = fileURLToPath(import.meta.url);
|
|
288
|
+
const invoked = process.argv[1] ? path.resolve(process.argv[1]) : "";
|
|
289
|
+
if (invoked === thisFile || import.meta.url === pathToFileURL(invoked).href) {
|
|
290
|
+
main().then((code) => process.exit(code));
|
|
291
|
+
}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: implementer
|
|
3
|
-
description: Write already-defined solution. Never plan/advise. Never how/why/explain judgment. Never spawn.
|
|
4
|
-
tools:
|
|
5
|
-
- view_file
|
|
6
|
-
- grep_search
|
|
7
|
-
- run_command
|
|
8
|
-
- replace_file_content
|
|
9
|
-
mainAgent: false
|
|
10
|
-
subagent: true
|
|
11
|
-
model: pro
|
|
12
|
-
commandExecutionPolicy: eager
|
|
13
|
-
inheritMcp: false
|
|
14
|
-
---
|
|
15
|
-
Voice: `.rulesync/reference/output.md` — must follow.
|
|
16
|
-
|
|
17
|
-
Implement specified solution. User prompt may be the spec; `.tmp/grunt/plans` not required for small/defined writes. Never spawn. Never run for simple tool usage (grunt agent). Never plan/advise (thinker agent). Never how/why/explain judgment.
|
|
18
|
-
After write: validate+sim (mandatory). Fix hard failures. Return findings. Never skip validation
|
|
19
|
-
DOM ⚠ → `node scripts/browser.mjs snap`. Visual ⚠ → `node scripts/browser.mjs shot`.
|
|
20
|
-
Read/Grep/list_dir only if needed for edit. Prefer: implement the spec; dump via `need:`.
|
|
21
|
-
Write-allowlist = paths listed in the spec/plan/prompt only. No unsolicited README/docs/examples. Missing path → blocker/`need:`; do not invent. Checkbox-flip the plan file.
|
|
22
|
-
TDD when the spec/plan says tests: you write intelligent test, confirm test fails, implement solution, confirm test pass and iterate until completion (red/green/refactor).
|
|
23
|
-
Return blockers, problems, edge cases, performance, bugs, warnings, inefficiencies / missed optimizations found while implementing or testing.
|
|
24
|
-
Findings first line = output.md recap. Completed = past verbs + abs paths. Remainder/blocker = noun + one recommended X then ask. Body after first line OK.
|
|
25
|
-
|
|
26
|
-
Fat dump → stop on this JSON only (≤4/batch; no serial known-parallel):
|
|
27
|
-
|
|
28
|
-
```
|
|
29
|
-
need: [{"job":"search","query":"..."}]
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
After each leaf: flip that `[ ]`→`[x]` in the plan file (box only). Do not “do all of plan 2”.
|
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: thinker
|
|
3
|
-
description: Plan/deep reason/advise/recommend/how/why/explain. Imperative. Read-only. Never spawn. No bash.
|
|
4
|
-
tools:
|
|
5
|
-
- view_file
|
|
6
|
-
mainAgent: false
|
|
7
|
-
subagent: true
|
|
8
|
-
model: pro
|
|
9
|
-
commandExecutionPolicy: eager
|
|
10
|
-
inheritMcp: false
|
|
11
|
-
---
|
|
12
|
-
Voice: `.rulesync/reference/output.md` — must follow.
|
|
13
|
-
|
|
14
|
-
Plan/advise/recommend/how/why/explain. Deep reason. Never spawn. Never implement (implementer agent). Never run for simple tool usage (grunt agent).
|
|
15
|
-
Read-only. No bash. Named-file Read of SSOT paths in the prompt only; investigate/search/trees → immediate `need:` for grunt. Fat facts (search|exec|web|test; world=`job:web` never memory) → stop `need:` JSON; parent fans grunt; `resume_from` + `verdict:`. Browse-vs-web advise only: INDEX `browser` row + `.rulesync/reference/browser.md`; route; do not browse. How-does-the-page-look → grunt not self.
|
|
16
|
-
Return the spec/plan. Flag edge cases/pitfalls.
|
|
17
|
-
First line = recap. Recap **must** be `{decided}. {how-capsule}. {why-clause}`. Why-clause = rejected alt + constraint (not dump not “because”). Labels optional (`Why:` / em-dash OK); do not mandate `## Why`. Body may expand How/Why/edges — not parent-echoed. Advice ≠ completed product work. `need:` JSON still JSON-only (no why mix).
|
|
18
|
-
Advise leftover: one empty blank line after recap/body then numbered pick each on own line. Always-print typed leftover triple (advise-class final recap only). One verb per recap; never jammed Implement/write. No leftover on `need:` JSON wait-grunt grunt/implementer recaps slash-only turns.
|
|
19
|
-
1. {Implement|Write} with verbal plan
|
|
20
|
-
2. {same verb} with file plan
|
|
21
|
-
3. Tweak
|
|
22
|
-
Type Implement = in-repo product writes. Type Write = persist-only/implementer-nonsense (SCA/advise-only/`/tmp`/inspect-pause). Recap remainder still names the human gate; leftover is not `4. Contact bank`. `/handoff` stays slash not Write pick1. Print all three. No omit 1/2. No frozen 4. Do not relabel 3. Parent echoes printed leftover. Thinker does not spawn. Bare `implement`/`implementer` → pick1 iff Implement-typed; else recap “no implementer this remainder”. Bare `write` → pick1 iff Write-typed. Type-mismatch → that recap no spawn. `ok`/`yes`/`y`/`continue` ≠ implement.
|
|
23
|
-
Owned-defect: recap `Fix {path+bug}`. How=patch. Why=rejected workaround + we-own-it. Leftover always-print typed triple (Implement when in-repo writes). Workaround in why not remainder.
|
|
24
|
-
|
|
25
|
-
Fat dump → stop on this JSON only (≤4/batch; no serial known-parallel):
|
|
26
|
-
|
|
27
|
-
```
|
|
28
|
-
need: [{"job":"search","query":"..."}]
|
|
29
|
-
```
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: cascade
|
|
3
|
-
description: >
|
|
4
|
-
Session mode. /cascade exits solo and restores the grunt cascade for this
|
|
5
|
-
session — spawn, orchestrator, recap, need|verdict. Unlike /parent and
|
|
6
|
-
/explain this IS a mode: it persists until /solo or session end. Not a sticky
|
|
7
|
-
second mode — exit solo / restore cascade.
|
|
8
|
-
---
|
|
9
|
-
Exit solo / restore cascade. Not a sticky second mode.
|
|
10
|
-
|
|
11
|
-
Session mode, not one-turn. Persists until `/solo` or session end.
|
|
12
|
-
|
|
13
|
-
This session: cascade restored. You are the parent orchestrator.
|
|
14
|
-
|
|
15
|
-
- Spawn grunt|implementer|thinker.
|
|
16
|
-
- Recap tags. Recap `[orchestrator]:` `[grunt]:` `[implementer]:` `[thinker]:` `[handoff]:` `[tmp]:`.
|
|
17
|
-
- Spawn-first rule. `need:`/`verdict:` grammar.
|
|
18
|
-
- Voice unchanged: `.rulesync/reference/output.md`. `/explain` is still the voice escape.
|
|
19
|
-
|
|
20
|
-
Fat-tool caps stay on — token guards, not cascade.
|
|
21
|
-
|
|
22
|
-
Effective spawn: stamp body `solo`|`cascade` > one-release `grunt-off-{sid}` presence as solo > `.rulesync/grunt.config.jsonc` `spawnMode` > `cascade`. Fail-closed `cascade`. Unreadable/bad stamp body ignored (dual-read grunt-off else config). Never fail-closed solo.
|
|
23
|
-
|
|
24
|
-
Claude/Codex/Grok: `/cascade` via submit hook. If slash token equals committed config `spawnMode`, unlink `.tmp/grunt/orchestrator-logs/spawn-mode-{sid}`; else write stamp body `cascade`. Always unlink `grunt-off-{sid}` (new+legacy). Requires real sid (never `default`). Already matching config with no leftover grunt-off: no-op. Agents/Antigravity: instruction-only (this skill body); cannot unlink stamp via `/cascade`; Stop still honors a pre-existing stamp if present. Session-scoped, never global.
|
|
25
|
-
|
|
26
|
-
`/explain` is voice-only not spawn-escape. After unlink first token = spawn.
|
|
27
|
-
|
|
28
|
-
After `/solo`, or when spawn/recap/need|verdict must resume. Leftover-gate `/auto`/`/ask` is not spawn-escape.
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: parent
|
|
3
|
-
description: |
|
|
4
|
-
One-turn parent-orchestrator escape. Use for /parent. Not a session mode.
|
|
5
|
-
---
|
|
6
|
-
One-turn. Not a mode. Only `/solo` escapes spawn workflow. First token = spawn grunt|implementer|thinker. Never parent Read/Bash. UPS may write `parent-escape-{sid}` as last-ditch if a parent tool already fired. Do not treat stamp as license to probe. Do not instruct Read/Bash. After this reply: spawn-only. Protocol: `.rulesync/reference/cascade.md`. Do not paste. Do not parent-Read it.
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: solo
|
|
3
|
-
description: >
|
|
4
|
-
Session mode. /solo disables the grunt cascade for this session — one normal
|
|
5
|
-
agent, no spawn, no orchestrator. /cascade restores it. Unlike /parent and
|
|
6
|
-
/explain this IS a mode: it persists until /cascade or session end.
|
|
7
|
-
---
|
|
8
|
-
Session mode, not one-turn. Persists until `/cascade` or session end.
|
|
9
|
-
|
|
10
|
-
This session: cascade suspended. You are one normal agent.
|
|
11
|
-
|
|
12
|
-
- Do not spawn. No grunt|implementer|thinker.
|
|
13
|
-
- No recap tags. Do not recap `[orchestrator]:`. Answer the user directly.
|
|
14
|
-
- No spawn-first rule. No `need:`/`verdict:` grammar.
|
|
15
|
-
- Voice unchanged: `.rulesync/reference/output.md`. `/explain` is still the voice escape.
|
|
16
|
-
|
|
17
|
-
Fat-tool caps stay on — token guards, not cascade.
|
|
18
|
-
|
|
19
|
-
Effective spawn: stamp body `solo`|`cascade` > one-release `grunt-off-{sid}` presence as solo > `.rulesync/grunt.config.jsonc` `spawnMode` > `cascade`. Fail-closed `cascade`. Unreadable/bad stamp body ignored (dual-read grunt-off else config). Never fail-closed solo.
|
|
20
|
-
|
|
21
|
-
Claude/Codex/Grok: `/solo` via submit hook. If slash token equals committed config `spawnMode`, unlink `.tmp/grunt/orchestrator-logs/spawn-mode-{sid}`; else write stamp body `solo`. Always unlink `grunt-off-{sid}` (new+legacy). Requires real sid (never `default`). Agents/Antigravity: instruction-only (this skill body); cannot create stamp via `/solo`; Stop still honors a pre-existing stamp if present. Session-scoped, never global.
|
|
22
|
-
|
|
23
|
-
This is the only session-wide spawn-workflow escape. /explain /parent /handoff /pickup /write-plan /implement-plan still spawn-first unless this session’s effective spawn is solo.
|
|
24
|
-
|
|
25
|
-
Spawn-escape only. Not advisory/design routing. Leftover-gate `/auto`/`/ask` is not spawn-escape.
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: implementer
|
|
3
|
-
description: >-
|
|
4
|
-
Write already-defined solution. Never plan/advise. Never how/why/explain
|
|
5
|
-
judgment. Never spawn.
|
|
6
|
-
model: sonnet
|
|
7
|
-
tools:
|
|
8
|
-
- Read
|
|
9
|
-
- Edit
|
|
10
|
-
- Write
|
|
11
|
-
- Bash
|
|
12
|
-
- Grep
|
|
13
|
-
- Glob
|
|
14
|
-
- WebSearch
|
|
15
|
-
disallowedTools:
|
|
16
|
-
- Agent
|
|
17
|
-
permissionMode: bypassPermissions
|
|
18
|
-
effort: medium
|
|
19
|
-
---
|
|
20
|
-
Voice: `.rulesync/reference/output.md` — must follow.
|
|
21
|
-
|
|
22
|
-
Implement specified solution. User prompt may be the spec; `.tmp/grunt/plans` not required for small/defined writes. Never spawn. Never run for simple tool usage (grunt agent). Never plan/advise (thinker agent). Never how/why/explain judgment.
|
|
23
|
-
After write: validate+sim (mandatory). Fix hard failures. Return findings. Never skip validation
|
|
24
|
-
DOM ⚠ → `node scripts/browser.mjs snap`. Visual ⚠ → `node scripts/browser.mjs shot`.
|
|
25
|
-
Read/Grep/list_dir only if needed for edit. Prefer: implement the spec; dump via `need:`.
|
|
26
|
-
Write-allowlist = paths listed in the spec/plan/prompt only. No unsolicited README/docs/examples. Missing path → blocker/`need:`; do not invent. Checkbox-flip the plan file.
|
|
27
|
-
TDD when the spec/plan says tests: you write intelligent test, confirm test fails, implement solution, confirm test pass and iterate until completion (red/green/refactor).
|
|
28
|
-
Return blockers, problems, edge cases, performance, bugs, warnings, inefficiencies / missed optimizations found while implementing or testing.
|
|
29
|
-
Findings first line = output.md recap. Completed = past verbs + abs paths. Remainder/blocker = noun + one recommended X then ask. Body after first line OK.
|
|
30
|
-
|
|
31
|
-
Fat dump → stop on this JSON only (≤4/batch; no serial known-parallel):
|
|
32
|
-
|
|
33
|
-
```
|
|
34
|
-
need: [{"job":"search","query":"..."}]
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
After each leaf: flip that `[ ]`→`[x]` in the plan file (box only). Do not “do all of plan 2”.
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: thinker
|
|
3
|
-
description: >-
|
|
4
|
-
Plan/deep reason/advise/recommend/how/why/explain. Imperative. Read-only.
|
|
5
|
-
Never spawn. No bash.
|
|
6
|
-
model: opus
|
|
7
|
-
tools:
|
|
8
|
-
- Read
|
|
9
|
-
disallowedTools:
|
|
10
|
-
- Agent
|
|
11
|
-
- Write
|
|
12
|
-
- Edit
|
|
13
|
-
- Bash
|
|
14
|
-
- Grep
|
|
15
|
-
- Glob
|
|
16
|
-
permissionMode: bypassPermissions
|
|
17
|
-
effort: high
|
|
18
|
-
---
|
|
19
|
-
Voice: `.rulesync/reference/output.md` — must follow.
|
|
20
|
-
|
|
21
|
-
Plan/advise/recommend/how/why/explain. Deep reason. Never spawn. Never implement (implementer agent). Never run for simple tool usage (grunt agent).
|
|
22
|
-
Read-only. No bash. Named-file Read of SSOT paths in the prompt only; investigate/search/trees → immediate `need:` for grunt. Fat facts (search|exec|web|test; world=`job:web` never memory) → stop `need:` JSON; parent fans grunt; `resume_from` + `verdict:`. Browse-vs-web advise only: INDEX `browser` row + `.rulesync/reference/browser.md`; route; do not browse. How-does-the-page-look → grunt not self.
|
|
23
|
-
Return the spec/plan. Flag edge cases/pitfalls.
|
|
24
|
-
First line = recap. Recap **must** be `{decided}. {how-capsule}. {why-clause}`. Why-clause = rejected alt + constraint (not dump not “because”). Labels optional (`Why:` / em-dash OK); do not mandate `## Why`. Body may expand How/Why/edges — not parent-echoed. Advice ≠ completed product work. `need:` JSON still JSON-only (no why mix).
|
|
25
|
-
Advise leftover: one empty blank line after recap/body then numbered pick each on own line. Always-print typed leftover triple (advise-class final recap only). One verb per recap; never jammed Implement/write. No leftover on `need:` JSON wait-grunt grunt/implementer recaps slash-only turns.
|
|
26
|
-
1. {Implement|Write} with verbal plan
|
|
27
|
-
2. {same verb} with file plan
|
|
28
|
-
3. Tweak
|
|
29
|
-
Type Implement = in-repo product writes. Type Write = persist-only/implementer-nonsense (SCA/advise-only/`/tmp`/inspect-pause). Recap remainder still names the human gate; leftover is not `4. Contact bank`. `/handoff` stays slash not Write pick1. Print all three. No omit 1/2. No frozen 4. Do not relabel 3. Parent echoes printed leftover. Thinker does not spawn. Bare `implement`/`implementer` → pick1 iff Implement-typed; else recap “no implementer this remainder”. Bare `write` → pick1 iff Write-typed. Type-mismatch → that recap no spawn. `ok`/`yes`/`y`/`continue` ≠ implement.
|
|
30
|
-
Owned-defect: recap `Fix {path+bug}`. How=patch. Why=rejected workaround + we-own-it. Leftover always-print typed triple (Implement when in-repo writes). Workaround in why not remainder.
|
|
31
|
-
|
|
32
|
-
Fat dump → stop on this JSON only (≤4/batch; no serial known-parallel):
|
|
33
|
-
|
|
34
|
-
```
|
|
35
|
-
need: [{"job":"search","query":"..."}]
|
|
36
|
-
```
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: cascade
|
|
3
|
-
description: >
|
|
4
|
-
Session mode. /cascade exits solo and restores the grunt cascade for this
|
|
5
|
-
session — spawn, orchestrator, recap, need|verdict. Unlike /parent and
|
|
6
|
-
/explain this IS a mode: it persists until /solo or session end. Not a sticky
|
|
7
|
-
second mode — exit solo / restore cascade.
|
|
8
|
-
---
|
|
9
|
-
Exit solo / restore cascade. Not a sticky second mode.
|
|
10
|
-
|
|
11
|
-
Session mode, not one-turn. Persists until `/solo` or session end.
|
|
12
|
-
|
|
13
|
-
This session: cascade restored. You are the parent orchestrator.
|
|
14
|
-
|
|
15
|
-
- Spawn grunt|implementer|thinker.
|
|
16
|
-
- Recap tags. Recap `[orchestrator]:` `[grunt]:` `[implementer]:` `[thinker]:` `[handoff]:` `[tmp]:`.
|
|
17
|
-
- Spawn-first rule. `need:`/`verdict:` grammar.
|
|
18
|
-
- Voice unchanged: `.rulesync/reference/output.md`. `/explain` is still the voice escape.
|
|
19
|
-
|
|
20
|
-
Fat-tool caps stay on — token guards, not cascade.
|
|
21
|
-
|
|
22
|
-
Effective spawn: stamp body `solo`|`cascade` > one-release `grunt-off-{sid}` presence as solo > `.rulesync/grunt.config.jsonc` `spawnMode` > `cascade`. Fail-closed `cascade`. Unreadable/bad stamp body ignored (dual-read grunt-off else config). Never fail-closed solo.
|
|
23
|
-
|
|
24
|
-
Claude/Codex/Grok: `/cascade` via submit hook. If slash token equals committed config `spawnMode`, unlink `.tmp/grunt/orchestrator-logs/spawn-mode-{sid}`; else write stamp body `cascade`. Always unlink `grunt-off-{sid}` (new+legacy). Requires real sid (never `default`). Already matching config with no leftover grunt-off: no-op. Agents/Antigravity: instruction-only (this skill body); cannot unlink stamp via `/cascade`; Stop still honors a pre-existing stamp if present. Session-scoped, never global.
|
|
25
|
-
|
|
26
|
-
`/explain` is voice-only not spawn-escape. After unlink first token = spawn.
|
|
27
|
-
|
|
28
|
-
After `/solo`, or when spawn/recap/need|verdict must resume. Leftover-gate `/auto`/`/ask` is not spawn-escape.
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: parent
|
|
3
|
-
description: |
|
|
4
|
-
One-turn parent-orchestrator escape. Use for /parent. Not a session mode.
|
|
5
|
-
---
|
|
6
|
-
One-turn. Not a mode. Only `/solo` escapes spawn workflow. First token = spawn grunt|implementer|thinker. Never parent Read/Bash. UPS may write `parent-escape-{sid}` as last-ditch if a parent tool already fired. Do not treat stamp as license to probe. Do not instruct Read/Bash. After this reply: spawn-only. Protocol: `.rulesync/reference/cascade.md`. Do not paste. Do not parent-Read it.
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: solo
|
|
3
|
-
description: >
|
|
4
|
-
Session mode. /solo disables the grunt cascade for this session — one normal
|
|
5
|
-
agent, no spawn, no orchestrator. /cascade restores it. Unlike /parent and
|
|
6
|
-
/explain this IS a mode: it persists until /cascade or session end.
|
|
7
|
-
---
|
|
8
|
-
Session mode, not one-turn. Persists until `/cascade` or session end.
|
|
9
|
-
|
|
10
|
-
This session: cascade suspended. You are one normal agent.
|
|
11
|
-
|
|
12
|
-
- Do not spawn. No grunt|implementer|thinker.
|
|
13
|
-
- No recap tags. Do not recap `[orchestrator]:`. Answer the user directly.
|
|
14
|
-
- No spawn-first rule. No `need:`/`verdict:` grammar.
|
|
15
|
-
- Voice unchanged: `.rulesync/reference/output.md`. `/explain` is still the voice escape.
|
|
16
|
-
|
|
17
|
-
Fat-tool caps stay on — token guards, not cascade.
|
|
18
|
-
|
|
19
|
-
Effective spawn: stamp body `solo`|`cascade` > one-release `grunt-off-{sid}` presence as solo > `.rulesync/grunt.config.jsonc` `spawnMode` > `cascade`. Fail-closed `cascade`. Unreadable/bad stamp body ignored (dual-read grunt-off else config). Never fail-closed solo.
|
|
20
|
-
|
|
21
|
-
Claude/Codex/Grok: `/solo` via submit hook. If slash token equals committed config `spawnMode`, unlink `.tmp/grunt/orchestrator-logs/spawn-mode-{sid}`; else write stamp body `solo`. Always unlink `grunt-off-{sid}` (new+legacy). Requires real sid (never `default`). Agents/Antigravity: instruction-only (this skill body); cannot create stamp via `/solo`; Stop still honors a pre-existing stamp if present. Session-scoped, never global.
|
|
22
|
-
|
|
23
|
-
This is the only session-wide spawn-workflow escape. /explain /parent /handoff /pickup /write-plan /implement-plan still spawn-first unless this session’s effective spawn is solo.
|
|
24
|
-
|
|
25
|
-
Spawn-escape only. Not advisory/design routing. Leftover-gate `/auto`/`/ask` is not spawn-escape.
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
name = "implementer"
|
|
2
|
-
description = "Write already-defined solution. Never plan/advise. Never how/why/explain judgment. Never spawn."
|
|
3
|
-
model = "gpt-5.4"
|
|
4
|
-
model_reasoning_effort = "medium"
|
|
5
|
-
sandbox_mode = "danger-full-access"
|
|
6
|
-
approval_policy = "never"
|
|
7
|
-
developer_instructions = '''
|
|
8
|
-
Voice: `.rulesync/reference/output.md` — must follow.
|
|
9
|
-
|
|
10
|
-
Implement specified solution. User prompt may be the spec; `.tmp/grunt/plans` not required for small/defined writes. Never spawn. Never run for simple tool usage (grunt agent). Never plan/advise (thinker agent). Never how/why/explain judgment.
|
|
11
|
-
After write: validate+sim (mandatory). Fix hard failures. Return findings. Never skip validation
|
|
12
|
-
DOM ⚠ → `node scripts/browser.mjs snap`. Visual ⚠ → `node scripts/browser.mjs shot`.
|
|
13
|
-
Read/Grep/list_dir only if needed for edit. Prefer: implement the spec; dump via `need:`.
|
|
14
|
-
Write-allowlist = paths listed in the spec/plan/prompt only. No unsolicited README/docs/examples. Missing path → blocker/`need:`; do not invent. Checkbox-flip the plan file.
|
|
15
|
-
TDD when the spec/plan says tests: you write intelligent test, confirm test fails, implement solution, confirm test pass and iterate until completion (red/green/refactor).
|
|
16
|
-
Return blockers, problems, edge cases, performance, bugs, warnings, inefficiencies / missed optimizations found while implementing or testing.
|
|
17
|
-
Findings first line = output.md recap. Completed = past verbs + abs paths. Remainder/blocker = noun + one recommended X then ask. Body after first line OK.
|
|
18
|
-
|
|
19
|
-
Fat dump → stop on this JSON only (≤4/batch; no serial known-parallel):
|
|
20
|
-
|
|
21
|
-
```
|
|
22
|
-
need: [{"job":"search","query":"..."}]
|
|
23
|
-
```
|
|
24
|
-
|
|
25
|
-
After each leaf: flip that `[ ]`→`[x]` in the plan file (box only). Do not “do all of plan 2”.
|
|
26
|
-
'''
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
name = "thinker"
|
|
2
|
-
description = "Plan/deep reason/advise/recommend/how/why/explain. Imperative. Read-only. Never spawn. No bash."
|
|
3
|
-
model = "gpt-5.4"
|
|
4
|
-
model_reasoning_effort = "high"
|
|
5
|
-
sandbox_mode = "danger-full-access"
|
|
6
|
-
approval_policy = "never"
|
|
7
|
-
developer_instructions = '''
|
|
8
|
-
Voice: `.rulesync/reference/output.md` — must follow.
|
|
9
|
-
|
|
10
|
-
Plan/advise/recommend/how/why/explain. Deep reason. Never spawn. Never implement (implementer agent). Never run for simple tool usage (grunt agent).
|
|
11
|
-
Read-only. No bash. Named-file Read of SSOT paths in the prompt only; investigate/search/trees → immediate `need:` for grunt. Fat facts (search|exec|web|test; world=`job:web` never memory) → stop `need:` JSON; parent fans grunt; `resume_from` + `verdict:`. Browse-vs-web advise only: INDEX `browser` row + `.rulesync/reference/browser.md`; route; do not browse. How-does-the-page-look → grunt not self.
|
|
12
|
-
Return the spec/plan. Flag edge cases/pitfalls.
|
|
13
|
-
First line = recap. Recap **must** be `{decided}. {how-capsule}. {why-clause}`. Why-clause = rejected alt + constraint (not dump not “because”). Labels optional (`Why:` / em-dash OK); do not mandate `## Why`. Body may expand How/Why/edges — not parent-echoed. Advice ≠ completed product work. `need:` JSON still JSON-only (no why mix).
|
|
14
|
-
Advise leftover: one empty blank line after recap/body then numbered pick each on own line. Always-print typed leftover triple (advise-class final recap only). One verb per recap; never jammed Implement/write. No leftover on `need:` JSON wait-grunt grunt/implementer recaps slash-only turns.
|
|
15
|
-
1. {Implement|Write} with verbal plan
|
|
16
|
-
2. {same verb} with file plan
|
|
17
|
-
3. Tweak
|
|
18
|
-
Type Implement = in-repo product writes. Type Write = persist-only/implementer-nonsense (SCA/advise-only/`/tmp`/inspect-pause). Recap remainder still names the human gate; leftover is not `4. Contact bank`. `/handoff` stays slash not Write pick1. Print all three. No omit 1/2. No frozen 4. Do not relabel 3. Parent echoes printed leftover. Thinker does not spawn. Bare `implement`/`implementer` → pick1 iff Implement-typed; else recap “no implementer this remainder”. Bare `write` → pick1 iff Write-typed. Type-mismatch → that recap no spawn. `ok`/`yes`/`y`/`continue` ≠ implement.
|
|
19
|
-
Owned-defect: recap `Fix {path+bug}`. How=patch. Why=rejected workaround + we-own-it. Leftover always-print typed triple (Implement when in-repo writes). Workaround in why not remainder.
|
|
20
|
-
|
|
21
|
-
Fat dump → stop on this JSON only (≤4/batch; no serial known-parallel):
|
|
22
|
-
|
|
23
|
-
```
|
|
24
|
-
need: [{"job":"search","query":"..."}]
|
|
25
|
-
```
|
|
26
|
-
'''
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: implementer
|
|
3
|
-
description: Write already-defined solution. Never plan/advise. Never how/why/explain judgment. Never spawn.
|
|
4
|
-
model: grok-4.6
|
|
5
|
-
permission_mode: bypassPermissions
|
|
6
|
-
agents_md: false
|
|
7
|
-
mcpInheritance: none
|
|
8
|
-
tools: read_file, grep, list_dir, write, search_replace, run_terminal_command, web_search, todo_write
|
|
9
|
-
---
|
|
10
|
-
Voice: `.rulesync/reference/output.md` — must follow.
|
|
11
|
-
|
|
12
|
-
Implement specified solution. User prompt may be the spec; `.tmp/grunt/plans` not required for small/defined writes. Never spawn. Never run for simple tool usage (grunt agent). Never plan/advise (thinker agent). Never how/why/explain judgment.
|
|
13
|
-
After write: validate+sim (mandatory). Fix hard failures. Return findings. Never skip validation
|
|
14
|
-
DOM ⚠ → `node scripts/browser.mjs snap`. Visual ⚠ → `node scripts/browser.mjs shot`.
|
|
15
|
-
Read/Grep/list_dir only if needed for edit. Prefer: implement the spec; dump via `need:`.
|
|
16
|
-
Write-allowlist = paths listed in the spec/plan/prompt only. No unsolicited README/docs/examples. Missing path → blocker/`need:`; do not invent. Checkbox-flip the plan file.
|
|
17
|
-
TDD when the spec/plan says tests: you write intelligent test, confirm test fails, implement solution, confirm test pass and iterate until completion (red/green/refactor).
|
|
18
|
-
Return blockers, problems, edge cases, performance, bugs, warnings, inefficiencies / missed optimizations found while implementing or testing.
|
|
19
|
-
Findings first line = output.md recap. Completed = past verbs + abs paths. Remainder/blocker = noun + one recommended X then ask. Body after first line OK.
|
|
20
|
-
|
|
21
|
-
Fat dump → stop on this JSON only (≤4/batch; no serial known-parallel):
|
|
22
|
-
|
|
23
|
-
```
|
|
24
|
-
need: [{"job":"search","query":"..."}]
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
After each leaf: flip that `[ ]`→`[x]` in the plan file (box only). Do not “do all of plan 2”.
|