@aicopycoders/exodus 2026.9.1100-beta.2 → 2026.9.1400-beta.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/assets/docs/CLAUDE.md +22 -1
- package/assets/docs/PIPELINES.md +20 -0
- package/assets/skills/anatomy-of-ads/SKILL.md +138 -0
- package/assets/skills/anatomy-of-ads/references/beat-map.md +69 -0
- package/assets/skills/anatomy-of-ads/references/concept-angle.md +50 -0
- package/assets/skills/anatomy-of-ads/references/hook-and-structure.md +69 -0
- package/assets/skills/bot-builder/SKILL.md +147 -0
- package/assets/skills/bot-builder/references/exodus-prompt-node.md +113 -0
- package/assets/skills/bot-builder/references/prompt-blocks.md +169 -0
- package/assets/skills/copy-instincts/SKILL.md +154 -0
- package/assets/skills/copy-instincts/references/instincts-catalog.md +131 -0
- package/assets/skills/copy-instincts/references/locked-examples.md +104 -0
- package/assets/skills/copy-instincts/references/worked-runs.md +148 -0
- package/assets/skills/exodus/SKILL.md +10 -1
- package/assets/skills/exodus-video/SKILL.md +12 -4
- package/assets/skills/exodus-video/scripts/first-cut.mjs +129 -32
- package/assets/skills/find-competitors/SKILL.md +148 -0
- package/assets/skills/find-competitors/references/query-grid.md +78 -0
- package/assets/skills/find-competitors/scripts/__pycache__/adlib_sweep.cpython-314.pyc +0 -0
- package/assets/skills/find-competitors/scripts/__pycache__/competitor_signals.cpython-314.pyc +0 -0
- package/assets/skills/find-competitors/scripts/adlib_sweep.py +100 -0
- package/assets/skills/find-competitors/scripts/competitor_signals.py +168 -0
- package/assets/skills/handoff/SKILL.md +81 -0
- package/assets/skills/mechanism/SKILL.md +130 -0
- package/assets/skills/mechanism/references/bot-prompts.md +94 -0
- package/assets/skills/mechanism/references/competitor-mechanisms.md +39 -0
- package/assets/skills/odf/SKILL.md +167 -0
- package/assets/skills/patterns-and-gaps/SKILL.md +120 -0
- package/assets/skills/positioning-spiral/SKILL.md +166 -0
- package/assets/skills/remember-that/SKILL.md +56 -0
- package/assets/skills/segment-grid/README.md +45 -0
- package/assets/skills/segment-grid/SKILL.md +84 -0
- package/assets/skills/thinking-vs-build/SKILL.md +120 -0
- package/assets/templates/STANDARDS.md +49 -0
- package/dist/commands/init.d.ts +1 -0
- package/dist/commands/init.js +10 -5
- package/dist/commands/update.js +1 -1
- package/dist/commands/video.d.ts +6 -0
- package/dist/commands/video.js +30 -1
- package/dist/lib/assets.d.ts +1 -0
- package/dist/lib/assets.js +3 -0
- package/dist/lib/scaffold.d.ts +3 -0
- package/dist/lib/scaffold.js +18 -1
- package/package.json +1 -1
package/dist/commands/video.js
CHANGED
|
@@ -362,12 +362,19 @@ export function planPull(run, items, opts) {
|
|
|
362
362
|
durationSec: artifact.durationSec ?? null,
|
|
363
363
|
qc: artifact.qc ?? null,
|
|
364
364
|
words: artifact.words ?? null,
|
|
365
|
+
revoiced: artifact.revoiced === true,
|
|
366
|
+
speechTrimmed: artifact.speechTrimmed === true,
|
|
365
367
|
});
|
|
366
368
|
}
|
|
367
369
|
const clipItemByScene = new Map();
|
|
370
|
+
const frameItemByScene = new Map();
|
|
371
|
+
const sceneFrameNodeIds = new Set(run.nodes.filter((n) => n.kind === "scene-frames").map((n) => n.nodeId));
|
|
368
372
|
for (const item of items) {
|
|
369
373
|
if (item.itemKind === "clip")
|
|
370
374
|
clipItemByScene.set(item.sceneIndex, item);
|
|
375
|
+
if (item.itemKind === "frame" && sceneFrameNodeIds.has(item.nodeId)) {
|
|
376
|
+
frameItemByScene.set(item.sceneIndex, item);
|
|
377
|
+
}
|
|
371
378
|
}
|
|
372
379
|
const sceneIndexes = [
|
|
373
380
|
...new Set([
|
|
@@ -375,12 +382,14 @@ export function planPull(run, items, opts) {
|
|
|
375
382
|
...voiceByScene.keys(),
|
|
376
383
|
...keyframeByScene.keys(),
|
|
377
384
|
...clipItemByScene.keys(),
|
|
385
|
+
...frameItemByScene.keys(),
|
|
378
386
|
]),
|
|
379
387
|
].sort((a, b) => a - b);
|
|
380
388
|
const scenes = sceneIndexes.map((sceneIndex) => {
|
|
381
389
|
const clip = clipByScene.get(sceneIndex);
|
|
382
390
|
const voice = voiceByScene.get(sceneIndex);
|
|
383
391
|
const item = clipItemByScene.get(sceneIndex);
|
|
392
|
+
const frameItem = frameItemByScene.get(sceneIndex);
|
|
384
393
|
let source = null;
|
|
385
394
|
let wordsFrom = null;
|
|
386
395
|
if (clip?.words && clip.words.length > 0) {
|
|
@@ -405,10 +414,13 @@ export function planPull(run, items, opts) {
|
|
|
405
414
|
voice: voice?.download.file ?? null,
|
|
406
415
|
keyframe: keyframeByScene.get(sceneIndex)?.file ?? null,
|
|
407
416
|
qc: clip?.qc ?? null,
|
|
417
|
+
revoiced: clip ? clip.revoiced : null,
|
|
418
|
+
speechTrimmed: clip ? clip.speechTrimmed : null,
|
|
408
419
|
clipStatus: item?.status ?? "missing",
|
|
409
420
|
error: item?.error ?? null,
|
|
410
421
|
flagged: item?.flagged === true,
|
|
411
422
|
findings: item?.findings ?? [],
|
|
423
|
+
keyframeFindings: frameItem?.findings ?? [],
|
|
412
424
|
};
|
|
413
425
|
});
|
|
414
426
|
const downloads = [
|
|
@@ -444,8 +456,11 @@ export function markPullFailure(manifest, failure) {
|
|
|
444
456
|
for (const scene of manifest.scenes) {
|
|
445
457
|
const lostWordsSource = (scene.clip === failure.file && scene.wordsFrom === "clip") ||
|
|
446
458
|
(scene.voice === failure.file && scene.wordsFrom === "voice");
|
|
447
|
-
if (scene.clip === failure.file)
|
|
459
|
+
if (scene.clip === failure.file) {
|
|
448
460
|
scene.clip = null;
|
|
461
|
+
scene.revoiced = null;
|
|
462
|
+
scene.speechTrimmed = null;
|
|
463
|
+
}
|
|
449
464
|
if (scene.voice === failure.file)
|
|
450
465
|
scene.voice = null;
|
|
451
466
|
if (scene.keyframe === failure.file)
|
|
@@ -648,11 +663,20 @@ export async function statusFlow(runId, json, deps) {
|
|
|
648
663
|
if (json) {
|
|
649
664
|
return { code: 0, lines: [JSON.stringify({ runId, status: run.status, stop, items, hasFinal })] };
|
|
650
665
|
}
|
|
666
|
+
const revoicedByScene = new Set();
|
|
667
|
+
for (const artifact of outputsOfNodeKind(run, "video")) {
|
|
668
|
+
if (artifact.type === "video" && artifact.revoiced === true && typeof artifact.sceneIndex === "number") {
|
|
669
|
+
revoicedByScene.add(artifact.sceneIndex);
|
|
670
|
+
}
|
|
671
|
+
}
|
|
651
672
|
const byScene = new Map();
|
|
673
|
+
const sceneFrameNodeIds = new Set(run.nodes.filter((n) => n.kind === "scene-frames").map((n) => n.nodeId));
|
|
652
674
|
for (const item of items) {
|
|
653
675
|
if (item.itemKind !== "clip" && item.itemKind !== "voiceover" && item.itemKind !== "frame") {
|
|
654
676
|
continue;
|
|
655
677
|
}
|
|
678
|
+
if (item.itemKind === "frame" && !sceneFrameNodeIds.has(item.nodeId))
|
|
679
|
+
continue;
|
|
656
680
|
const row = byScene.get(item.sceneIndex) ?? {};
|
|
657
681
|
row[item.itemKind] = item;
|
|
658
682
|
byScene.set(item.sceneIndex, row);
|
|
@@ -674,6 +698,11 @@ export async function statusFlow(runId, json, deps) {
|
|
|
674
698
|
}
|
|
675
699
|
if (row.clip?.error)
|
|
676
700
|
lines.push(` ${row.clip.error}`);
|
|
701
|
+
if (revoicedByScene.has(sceneIndex))
|
|
702
|
+
lines.push(" voice: cast voice applied");
|
|
703
|
+
for (const finding of row.frame?.findings ?? []) {
|
|
704
|
+
lines.push(` picture: ${finding.code} (${finding.severity}): ${finding.detail}`);
|
|
705
|
+
}
|
|
677
706
|
}
|
|
678
707
|
}
|
|
679
708
|
lines.push("", hasFinal && stop.at === "finished"
|
package/dist/lib/assets.d.ts
CHANGED
|
@@ -2,3 +2,4 @@ export declare function assetsRoot(override?: string): string;
|
|
|
2
2
|
export declare function skillsDir(override?: string): string;
|
|
3
3
|
export declare function referencesDir(override?: string): string;
|
|
4
4
|
export declare function docsDir(override?: string): string;
|
|
5
|
+
export declare function templatesDir(override?: string): string;
|
package/dist/lib/assets.js
CHANGED
package/dist/lib/scaffold.d.ts
CHANGED
|
@@ -7,4 +7,7 @@ export declare function ensureGitignore(root: string): void;
|
|
|
7
7
|
export declare function writeSkills(root: string, srcOverride?: string, channel?: Channel): string[];
|
|
8
8
|
export declare function writeReferences(root: string, srcOverride?: string, channel?: Channel): void;
|
|
9
9
|
export declare function writeDocs(root: string, srcOverride?: string, channel?: Channel): string[];
|
|
10
|
+
export declare function writeStandards(root: string, srcOverride?: string, channel?: Channel): {
|
|
11
|
+
created: boolean;
|
|
12
|
+
};
|
|
10
13
|
export declare function ensureBaseDirs(root: string): void;
|
package/dist/lib/scaffold.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
|
-
import { skillsDir, referencesDir, docsDir } from "./assets.js";
|
|
3
|
+
import { skillsDir, referencesDir, docsDir, templatesDir } from "./assets.js";
|
|
4
4
|
import { getChannel, stampChannel } from "./channel.js";
|
|
5
5
|
export const ENV_SCAFFOLD = `# Exodus config — paste your dashboard .env block below this line.
|
|
6
6
|
# Get it from your Exodus dashboard -> Settings -> Claude Code -> "Copy .env block".
|
|
@@ -91,6 +91,23 @@ export function writeDocs(root, srcOverride, channel = getChannel()) {
|
|
|
91
91
|
}
|
|
92
92
|
return names.sort();
|
|
93
93
|
}
|
|
94
|
+
export function writeStandards(root, srcOverride, channel = getChannel()) {
|
|
95
|
+
const dest = path.join(root, "STANDARDS.md");
|
|
96
|
+
if (fs.existsSync(dest))
|
|
97
|
+
return { created: false };
|
|
98
|
+
let src;
|
|
99
|
+
try {
|
|
100
|
+
src = templatesDir(srcOverride);
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
return { created: false };
|
|
104
|
+
}
|
|
105
|
+
const template = path.join(src, "STANDARDS.md");
|
|
106
|
+
if (!fs.existsSync(template))
|
|
107
|
+
return { created: false };
|
|
108
|
+
fs.writeFileSync(dest, stampChannel(fs.readFileSync(template, "utf8"), channel));
|
|
109
|
+
return { created: true };
|
|
110
|
+
}
|
|
94
111
|
export function ensureBaseDirs(root) {
|
|
95
112
|
const out = path.join(root, "output");
|
|
96
113
|
fs.mkdirSync(out, { recursive: true });
|