Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .claude/skills/release-video/actions/01-plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ The repository at the release candidate, read again from the last release tag, n
5. **Fixes.** List the `fix:` commits since the last release tag. A fix is worth a scene only when its before and after can be shown on screen; a fix that only makes figures or states more reliable has none. Group the ones that qualify into one `bullet-grid` scene; the usual outcome is no scene.
6. **Contributors.** Name who shipped the release with `gh api repos/{owner}/{repo}/compare/<last-tag>...next --jq '[.commits[].author.login] | unique'`. Drop bots, keep every human author whatever the type of the commit (a docs commit counts). Add whoever opened an issue closed since the last tag: `gh api "repos/{owner}/{repo}/issues?state=closed&since=<last-tag date>" --paginate --jq '[.[] | select(.pull_request == null) | .user.login] | unique'`, because someone who reported what a developer then fixed shipped it too. Put the logins in one `contributors` scene, last.
7. **Intro.** Fill `intro.highlights`, the tags that name the release's big features, so that someone who never used AIDD sees at a glance what it brings: up to five, each a short clear sentence of five words at most, starting from what the user gets (`Telemetry now covers Codex`, not `Report by tool`). Leave `tagline` out: a phrase above the tags says less than they do. Take the facts from the release announcement, so the video and the message say the same thing.
8. **YouTube text.** Fill `youtube` in French, in the words of the published videos: `themes` name the release's themes, `programme` has one line per covered surface saying what it does, as in `compter ce que coûte votre travail, par tâche`. `assets/youtube-metadata.js` assembles the title and the description in their published layout.
8. **YouTube text.** Fill `youtube` in French, in the words of the published videos: `themes` name the release's themes, `programme` has one line per covered surface saying what it does, as in `compter ce que coûte votre travail, par tâche`. Each line names its `theme`, one of `themes`: the announcements on Discord and Skool show one section per theme, with its lines as they are and its commands in parentheses, so each line is read as a sentence a member will see. `assets/youtube-metadata.js` assembles the title and the description in their published layout.
9. **Judge.** Read the plan against [judge.md](../references/judge.md), which the check cannot do.
10. **Check.** Rerun the check until it passes, then show the plan and fold corrections.

Expand Down
1 change: 1 addition & 0 deletions .claude/skills/release-video/assets/scenes-template.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
"programme": [
{
"surface": "aidd command",
"theme": "Theme one",
"text": "what it does for the user, in French."
}
]
Expand Down
8 changes: 6 additions & 2 deletions .claude/skills/release-video/assets/youtube-metadata.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ function titleOf(plan, version) {
}

function youtubeMetadata(plan, { version, tag, repo }) {
const contributors = plan.scenes.find((scene) => scene.template === "contributors")?.logins?.length;
const logins = plan.scenes.find((scene) => scene.template === "contributors")?.logins ?? [];
const contributors = logins.length;
const lines = [
`Les nouveautés du framework AI-Driven Dev ${version}, démontrées de bout en bout.`,
"",
Expand All @@ -30,7 +31,7 @@ function youtubeMetadata(plan, { version, tag, repo }) {
if (contributors) lines.push(`Version livrée par ${contributors} contributeurs (crédits dans les notes de version).`, "");
lines.push(`Notes de version : https://github.com/${repo}/releases/tag/${tag}`, `Code source : https://github.com/${repo}`);
const { themes, programme } = plan.youtube;
return { title: titleOf(plan, version), description: lines.join("\n"), themes, programme };
return { title: titleOf(plan, version), description: lines.join("\n"), themes, programme, contributors: logins };
}

/** What a plan lacks to be published: the block, a title that fits, a line for every scene's surface. */
Expand All @@ -40,6 +41,9 @@ function youtubeProblems(plan) {
const title = titleOf(plan, "0.0");
if (title.length > MAX_TITLE) problems.push(`title: ${title.length} characters, ${MAX_TITLE} at most`);
const covered = new Set(plan.youtube.programme.map((line) => line.surface));
for (const line of plan.youtube.programme) {
if (!plan.youtube.themes.includes(line.theme)) problems.push(`youtube programme: ${line.surface} has no theme from themes`);
}
for (const surface of plan.scenes.flatMap((scene) => scene.surfaces ?? [])) {
if (!covered.has(surface)) problems.push(`youtube programme: no line for ${surface}`);
}
Expand Down
2 changes: 1 addition & 1 deletion .claude/skills/release-video/references/scenes.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ What a plan holds and how each part is drawn.
| Plan field | Holds |
| --- | --- |
| `intro` | `highlights`, the tags shown first |
| `youtube` | `themes`, 1 to 4 short French theme names for the title; `programme`, one `{surface, text}` per surface a scene covers, `text` a French sentence that starts with a verb |
| `youtube` | `themes`, 1 to 4 short French theme names for the title; `programme`, one `{surface, theme, text}` per surface a scene covers, `theme` one of `themes`, `text` a French sentence that starts with a verb |

| Scene field | Holds |
| --- | --- |
Expand Down
2 changes: 1 addition & 1 deletion aidd_docs/memory/deployment.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ flowchart TD
- The Release PR merges with `--merge --admin`: the only method `.github/rulesets/main.json` allows, so `main` never holds merged but unversioned code.
- Tags: umbrella, `cli-v<semver>`, `<plugin>-v<semver>`. `scripts/credit-release-authors.cjs` appends each author as `(@login)`, a workaround until [googleapis/release-please#2892](https://github.com/googleapis/release-please/pull/2892) ships.
- The umbrella stays a draft until every asset is attached; its publication is the event n8n listens to.
- A failed video build keeps the release a draft, so nothing is announced without its video. A failed YouTube upload does not stop Discord and Skool: they post without the video link.
- A failed video build keeps the release a draft, so nothing is announced without its video. A failed YouTube upload does not stop Discord and Skool: they post without the video link. Their text is the video's programme, one section per theme, so the announcements say what the video shows.

Config: `release-please-config.json`, eleven packages. Manifest: `.release-please-manifest.json`.

Expand Down
5 changes: 5 additions & 0 deletions aidd_docs/release-video/scenes.json
Original file line number Diff line number Diff line change
Expand Up @@ -356,22 +356,27 @@
"programme": [
{
"surface": "aidd telemetry",
"theme": "Télémétrie",
"text": "compter aussi ce que coûte le travail fait avec Codex, avec le rapport complet."
},
{
"surface": "aidd-telemetry:00-init",
"theme": "Télémétrie",
"text": "activer la mesure et distinguer le résultat par outil, Claude Code ou Codex."
},
{
"surface": "aidd-dev:01-plan",
"theme": "Plan",
"text": "alléger le plan de moitié, y lister l'ordre des phases et l'impact, et le faire relire par un juge indépendant."
},
{
"surface": "aidd-refine:01-brainstorm",
"theme": "Brainstorm",
"text": "alléger le brainstorm et distinguer ce qui est établi, supposé ou resté ouvert."
},
{
"surface": "aidd-context:05-rule-generate",
"theme": "Règles",
"text": "vérifier qu'une règle n'en contredit pas une autre, et décider laquelle garder."
}
]
Expand Down
18 changes: 16 additions & 2 deletions scripts/__tests__/youtube-metadata.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ const plan = {
youtube: {
themes: ["Télémétrie", "Codex", "Règles"],
programme: [
{ surface: "aidd telemetry", text: "compter aussi le travail fait avec Codex." },
{ surface: "aidd-context:05-rule-generate", text: "vérifier qu'aucune règle n'en contredit une autre." },
{ surface: "aidd telemetry", theme: "Télémétrie", text: "compter aussi le travail fait avec Codex." },
{ surface: "aidd-context:05-rule-generate", theme: "Règles", text: "vérifier qu'aucune règle n'en contredit une autre." },
],
},
};
Expand Down Expand Up @@ -57,6 +57,11 @@ test("the themes and the programme travel with the text, so an announcement can
assert.deepEqual(metadata.programme, plan.youtube.programme);
});

test("the contributors of the video travel with the text, so the announcements credit the same people", () => {
assert.deepEqual(youtubeMetadata(plan, context).contributors, ["alexsoyes", "blafourcade"]);
assert.deepEqual(youtubeMetadata({ ...plan, scenes: plan.scenes.slice(0, 2) }, context).contributors, []);
});

test("a plugin skill is written as a slash command and a CLI command is left as it is", () => {
const { description } = youtubeMetadata(plan, context);

Expand All @@ -74,6 +79,15 @@ test("youtubeProblems accepts a plan whose programme covers every scene surface"
assert.deepEqual(youtubeProblems(plan), []);
});

test("youtubeProblems names a programme line whose theme is missing or not one of the themes", () => {
const [first, second] = plan.youtube.programme;
const bare = { ...plan, youtube: { ...plan.youtube, programme: [{ surface: first.surface, text: first.text }, second] } };
assert.deepEqual(youtubeProblems(bare), ["youtube programme: aidd telemetry has no theme from themes"]);

const foreign = { ...plan, youtube: { ...plan.youtube, programme: [{ ...first, theme: "Autre" }, second] } };
assert.deepEqual(youtubeProblems(foreign), ["youtube programme: aidd telemetry has no theme from themes"]);
});

test("youtubeProblems names a missing block, a title that is too long and an uncovered surface", () => {
assert.deepEqual(youtubeProblems({ scenes: [], skipped: [] }), ["youtube: missing"]);

Expand Down
Loading