@aicopycoders/exodus 2026.6.2400 → 2026.6.2700-beta.2
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/assets/skills/exodus-genesis/SKILL.md +13 -5
- package/assets/skills/exodus-write/SKILL.md +2 -0
- package/dist/commands/genesis.js +17 -1
- package/package.json +11 -3
- package/assets/skills/genesis-bots/.env.example +0 -12
- package/dist/commands/__tests__/genesis.hookgate.test.d.ts +0 -1
- package/dist/commands/__tests__/genesis.hookgate.test.js +0 -12
|
@@ -92,6 +92,9 @@ Save to `/tmp/genesis-seeds.txt` (one per line, `#` comments allowed), or pass `
|
|
|
92
92
|
**Pass count is the user's knob** — if they didn't specify, surface a quick menu (1 pass / 2 variants recommended · 2 passes / 4 variants · more) rather than assuming. Always `run_in_background: true` — these runs are past the 10-min foreground cap.
|
|
93
93
|
|
|
94
94
|
```bash
|
|
95
|
+
# Resolve hook mode FIRST (see "Hook selection mode" below) — these commands
|
|
96
|
+
# assume a saved default exists, else add --stop-at-hooks or --auto-hooks or they error.
|
|
97
|
+
|
|
95
98
|
# Default — 1 pass per bot = 2 variants (1 Mario × Brand + 1 Infeed × Brand):
|
|
96
99
|
npx @aicopycoders/exodus genesis run --brief "<brief>" --awareness <level>
|
|
97
100
|
|
|
@@ -110,12 +113,17 @@ npx @aicopycoders/exodus genesis run --brief "<brief>" --awareness <level> --aut
|
|
|
110
113
|
|
|
111
114
|
`--brief` accepts inline text or a file path. `--passes <n>` (1–5) is the friendly knob; `--variants <n>` (1–10) is an advanced raw-total override that wins if both are given.
|
|
112
115
|
|
|
113
|
-
**Hook
|
|
114
|
-
The pipeline can pause after
|
|
116
|
+
**Hook selection mode — REQUIRED gate before EVERY run (do not skip):**
|
|
117
|
+
The pipeline can pause after hook generation so the user picks which hooks become body copy — the human quality gate. You MUST resolve the mode **before** firing a run. A `genesis run` with **no** `--stop-at-hooks`/`--auto-hooks` **and** no saved preference now **hard-errors** (`Hook-selection preference not set`) **by design** — so the gate can't be silently skipped. If you see that error, you skipped this step; do it now.
|
|
118
|
+
|
|
119
|
+
Resolve it in this order, every time, BEFORE you run:
|
|
120
|
+
1. **Check the saved default:** run `npx @aicopycoders/exodus genesis hook-pref` (no argument). It prints `manual`, `auto`, or `unset` on the first line.
|
|
121
|
+
2. **If it prints `manual` or `auto`:** just fire the run — the saved default applies, no flag needed.
|
|
122
|
+
3. **If it prints `unset`:** STOP and ask the user once, plainly — *"Want to choose the hooks yourself before I write the copy, or have me auto-pick and write straight through?"* Then fire the run with the matching flag (`--stop-at-hooks` = they choose, `--auto-hooks` = auto), and after it starts, offer to save it as their default so you never ask again: `npx @aicopycoders/exodus genesis hook-pref <manual|auto>`. **Do NOT fire the run before they answer.**
|
|
115
123
|
|
|
116
|
-
|
|
117
|
-
- **`--
|
|
118
|
-
-
|
|
124
|
+
Flags:
|
|
125
|
+
- **`--stop-at-hooks`** — pause after hook generation. The run lands in `awaiting_hook_selection` and the CLI prints a dashboard URL; the user picks hooks on the run-detail page and the pipeline continues automatically to body copy.
|
|
126
|
+
- **`--auto-hooks`** — auto-pick the strongest hooks and write straight through (also overrides a saved "manual" default for this one run).
|
|
119
127
|
|
|
120
128
|
> "Genesis run started at problem-aware — 1 pass per bot (2 variants: Mario × Brand + Infeed × Brand). I'll surface the Doc when it lands."
|
|
121
129
|
|
|
@@ -122,6 +122,8 @@ Skip the menu only if the user already said how many ("just give me two", "run a
|
|
|
122
122
|
|
|
123
123
|
Hand off to the `exodus-genesis` skill — it owns the run (double-pass hooks, the built-in 15-point QA, the editing menu). Always background it; even the default run is ~12–15 min, past the 10-min foreground cap.
|
|
124
124
|
|
|
125
|
+
**Before firing, resolve the hook-selection gate** (the `exodus-genesis` skill's "Hook selection mode" step): run `npx @aicopycoders/exodus genesis hook-pref` — if it prints `unset`, ask the user *"choose the hooks yourself, or auto-pick and write straight through?"* and pass `--stop-at-hooks` or `--auto-hooks` accordingly (offer to save the choice). A run with no flag and no saved default hard-errors by design — don't skip this.
|
|
126
|
+
|
|
125
127
|
```bash
|
|
126
128
|
# Default — 1 pass per bot = 2 variants:
|
|
127
129
|
npx @aicopycoders/exodus genesis run --brief "<brief>" --awareness <level>
|
package/dist/commands/genesis.js
CHANGED
|
@@ -446,8 +446,24 @@ async function waitForGenesisRun(runId) {
|
|
|
446
446
|
async function runHookPref() {
|
|
447
447
|
const positionals = parsePositional();
|
|
448
448
|
const pref = positionals[1];
|
|
449
|
+
if (pref === undefined) {
|
|
450
|
+
const res = await apiGet("/api/v2/genesis/hook-pref");
|
|
451
|
+
if (!res.ok) {
|
|
452
|
+
console.log(`Error: ${res.data.error ?? "Unknown error"}`);
|
|
453
|
+
process.exit(1);
|
|
454
|
+
}
|
|
455
|
+
const cur = res.data.preference ?? null;
|
|
456
|
+
if (cur === null) {
|
|
457
|
+
console.log("unset");
|
|
458
|
+
console.log("No saved hook preference. Runs require --stop-at-hooks or --auto-hooks until one is set.");
|
|
459
|
+
}
|
|
460
|
+
else {
|
|
461
|
+
console.log(cur);
|
|
462
|
+
}
|
|
463
|
+
return;
|
|
464
|
+
}
|
|
449
465
|
if (pref !== "manual" && pref !== "auto") {
|
|
450
|
-
console.error('Usage: exodus genesis hook-pref
|
|
466
|
+
console.error('Usage: exodus genesis hook-pref [manual|auto] (no arg prints the current value)');
|
|
451
467
|
console.error(' manual Pause each run at hook selection so you choose hooks.');
|
|
452
468
|
console.error(' auto Skip hook selection and let the pipeline pick automatically.');
|
|
453
469
|
process.exit(1);
|
package/package.json
CHANGED
|
@@ -1,12 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aicopycoders/exodus",
|
|
3
|
-
"version": "2026.6.
|
|
3
|
+
"version": "2026.6.2700-beta.2",
|
|
4
4
|
"description": "CLI + Claude Code skills for the Copycoders Exodus ad pipeline",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "git+https://github.com/aicopycoders/exodus.git"
|
|
8
|
+
},
|
|
9
|
+
"homepage": "https://github.com/aicopycoders/exodus#readme",
|
|
5
10
|
"type": "module",
|
|
6
11
|
"bin": {
|
|
7
|
-
"exodus": "
|
|
12
|
+
"exodus": "dist/bin/exodus.js"
|
|
8
13
|
},
|
|
9
|
-
"files": [
|
|
14
|
+
"files": [
|
|
15
|
+
"dist",
|
|
16
|
+
"assets"
|
|
17
|
+
],
|
|
10
18
|
"engines": {
|
|
11
19
|
"node": ">=20"
|
|
12
20
|
},
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
# Genesis Bots credentials. Keep this file private — never commit or share it.
|
|
2
|
-
# Easiest: replace this ENTIRE file with what the portal's "Copy .env" button
|
|
3
|
-
# gives you (https://genesis.copycoders.ai/portal), then add your provider key.
|
|
4
|
-
|
|
5
|
-
GENESIS_BASE_URL=https://gas.copycoders.ai/api/v1
|
|
6
|
-
GENESIS_API_KEY=gen_your_key_here
|
|
7
|
-
|
|
8
|
-
# Your provider key (you pay usage). Use ONE of these — match the name to your key:
|
|
9
|
-
# Anthropic → ANTHROPIC_API_KEY=sk-ant-...
|
|
10
|
-
# OpenRouter → OPENROUTER_API_KEY=sk-or-...
|
|
11
|
-
# (`npx @aicopycoders/exodus keys pull` writes these names for you from the dashboard.)
|
|
12
|
-
ANTHROPIC_API_KEY=sk-ant-your_provider_key_here
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect } from "vitest";
|
|
2
|
-
import { buildBriefBody } from "../genesis.js";
|
|
3
|
-
describe("buildBriefBody stopAtHooks", () => {
|
|
4
|
-
it("omits stopAtHooks when unset", () => {
|
|
5
|
-
const b = buildBriefBody("brief text", { awarenessLevel: "problem-aware" });
|
|
6
|
-
expect("stopAtHooks" in b).toBe(false);
|
|
7
|
-
});
|
|
8
|
-
it("includes stopAtHooks:true when set", () => {
|
|
9
|
-
const b = buildBriefBody("brief text", { awarenessLevel: "problem-aware", stopAtHooks: true });
|
|
10
|
-
expect(b.stopAtHooks).toBe(true);
|
|
11
|
-
});
|
|
12
|
-
});
|