Merge branch 'refactor/task-translation-review-translation-review'
verify-and-publish / gate (push) Successful in 8m19s
verify-and-publish / publish (push) Has been skipped

Brings the i18n translation review into main:
- Five feat(i18n) commits translating the chapters collection
  (landing, summary, models, agents, skills).
- One feat(i18n) commit wiring audit-translations.mjs into
  pnpm run verify, with an 18-entry allowlist for intentional
  identicals (numeric card labels, product nouns, model-tier
  series names).

Together: 122 untranslated pt fields fixed (across 5 files), 18
intentional identicals documented, audit-translations now part of
the gate. English strings are byte-identical to origin/main. Recall
section in skills.json preserved byte-identical.

Reviewed-by: site owner (translation tone approved commit-by-commit).

Closes: chapters collection pt === en regression.
This commit is contained in:
Marcos Paulo
2026-09-07 04:58:08 -03:00
9 changed files with 396 additions and 151 deletions
@@ -0,0 +1,112 @@
{
"entries": [
{
"collection": "chapters",
"file": "agents.json",
"field": "sections.1.steps.0.label",
"reason": "Handoff step label (\"Brief\"); kept English by glossary convention."
},
{
"collection": "chapters",
"file": "landing.json",
"field": "cards.0.label",
"reason": "Numeric card label (\"01\"); identical across locales by design."
},
{
"collection": "chapters",
"file": "landing.json",
"field": "cards.1.label",
"reason": "Numeric card label (\"02\"); identical across locales by design."
},
{
"collection": "chapters",
"file": "landing.json",
"field": "cards.2.label",
"reason": "Numeric card label (\"03\"); identical across locales by design."
},
{
"collection": "chapters",
"file": "landing.json",
"field": "cards.2.title",
"reason": "Product noun (\"Skills\"); kept English by glossary convention."
},
{
"collection": "chapters",
"file": "landing.json",
"field": "cards.3.label",
"reason": "Numeric card label (\"04\"); identical across locales by design."
},
{
"collection": "chapters",
"file": "landing.json",
"field": "cards.4.label",
"reason": "Numeric card label (\"05\"); identical across locales by design."
},
{
"collection": "chapters",
"file": "landing.json",
"field": "cards.5.label",
"reason": "Numeric card label (\"06\"); identical across locales by design."
},
{
"collection": "chapters",
"file": "summary.json",
"field": "cards.0.label",
"reason": "Numeric card label (\"01\"); identical across locales by design."
},
{
"collection": "chapters",
"file": "summary.json",
"field": "cards.1.label",
"reason": "Numeric card label (\"02\"); identical across locales by design."
},
{
"collection": "chapters",
"file": "summary.json",
"field": "cards.2.label",
"reason": "Numeric card label (\"03\"); identical across locales by design."
},
{
"collection": "chapters",
"file": "summary.json",
"field": "cards.2.title",
"reason": "Product noun (\"Skills\"); kept English by glossary convention."
},
{
"collection": "chapters",
"file": "summary.json",
"field": "cards.3.label",
"reason": "Numeric card label (\"04\"); identical across locales by design."
},
{
"collection": "chapters",
"file": "summary.json",
"field": "cards.4.label",
"reason": "Numeric card label (\"05\"); identical across locales by design."
},
{
"collection": "chapters",
"file": "summary.json",
"field": "cards.5.label",
"reason": "Numeric card label (\"06\"); identical across locales by design."
},
{
"collection": "providers",
"file": "claude.json",
"field": "title",
"reason": "Model-tier series name (\"Opus · Sonnet · Haiku\"); kept English as product name."
},
{
"collection": "providers",
"file": "gemini.json",
"field": "title",
"reason": "Model-tier series name (\"Pro · Flash · Flash-Lite\"); kept English as product name."
},
{
"collection": "providers",
"file": "openai.json",
"field": "title",
"reason": "Model-tier series name (\"Sol · Terra · Luna\"); kept English as product name."
}
]
}
+96 -31
View File
@@ -7,16 +7,25 @@
// node .agents/scripts/audit-translations.mjs # walks src/content // node .agents/scripts/audit-translations.mjs # walks src/content
// node .agents/scripts/audit-translations.mjs src/content/ # explicit root // node .agents/scripts/audit-translations.mjs src/content/ # explicit root
// //
// Exits non-zero if any pair is identical. The output is grouped by // Exits non-zero if any unallowed pair is identical. The output is grouped
// collection, then by file, then by field path, so the report reads like // by collection, then by file, then by field path, so the report reads like
// a translation backlog rather than a wall of strings. // a translation backlog rather than a wall of strings.
// //
// This is the sibling of extract-strings.mjs: that one proves the // This is the sibling of extract-strings.mjs: that one proves the
// migration moved every string; this one proves every string actually // migration moved every string; this one proves every string actually
// differs across locales. // differs across locales.
//
// Allowlist: a sibling `.agents/scripts/audit-translations.allowlist.json`
// lists (collection, file, field) tuples that are intentionally identical
// across locales (numeric card labels, product nouns, model-tier series
// names, etc.). Entries in the allowlist are listed under "ALLOWED" in the
// output and do not affect the exit code. Adding to the allowlist is a
// deliberate edit + commit; future translators can see it and understand
// which identicals are intentional.
import { readFileSync, readdirSync, statSync } from 'node:fs'; import { existsSync, readFileSync, readdirSync, statSync } from 'node:fs';
import { join, relative } from 'node:path'; import { dirname, join, relative } from 'node:path';
import { fileURLToPath } from 'node:url';
const ROOT = process.argv[2] ?? 'src/content'; const ROOT = process.argv[2] ?? 'src/content';
@@ -69,9 +78,27 @@ const collectionOf = (file, root) => {
return parts.length >= 2 ? parts[0] : '(root)'; return parts.length >= 2 ? parts[0] : '(root)';
}; };
// Load the allowlist. The file lives next to this script and lists
// intentional identicals (numeric labels, product nouns, model-tier series
// names, etc.). Missing file is OK — the audit still runs.
const here = dirname(fileURLToPath(import.meta.url));
const allowlistPath = join(here, 'audit-translations.allowlist.json');
const allowlist = new Set();
const allowlistReasons = new Map();
if (existsSync(allowlistPath)) {
const { entries } = JSON.parse(readFileSync(allowlistPath, 'utf8'));
for (const { collection, file, field, reason } of entries) {
allowlist.add(`${collection}${file}${field}`);
allowlistReasons.set(`${collection}${file}${field}`, reason);
}
}
const groups = new Map(); const groups = new Map();
const allowedGroups = new Map();
let totalLocalized = 0; let totalLocalized = 0;
let totalIdentical = 0; let totalReal = 0;
let totalAllowed = 0;
for (const file of files) { for (const file of files) {
let data; let data;
@@ -84,40 +111,78 @@ for (const file of files) {
const pairs = collect(data); const pairs = collect(data);
if (pairs.length === 0) continue; if (pairs.length === 0) continue;
const offenders = pairs.filter(([, en, pt]) => same(en, pt));
if (offenders.length === 0) continue;
totalLocalized += pairs.length;
totalIdentical += offenders.length;
const collection = collectionOf(file, ROOT); const collection = collectionOf(file, ROOT);
const filename = relative(ROOT, file); const filename = relative(ROOT, file);
// Allowlist entries key on the file's name within its collection
// (e.g. `landing.json`), so strip the collection prefix from
// `filename` when matching. The full relative path is still used
// for the report display.
const collectionFile = filename.startsWith(collection + '/')
? filename.slice(collection.length + 1)
: filename;
if (!groups.has(collection)) groups.set(collection, []); // Split identical pairs into real offenders (fail the gate) and
groups.get(collection).push({ file: filename, pairs: offenders }); // allowlisted ones (listed under ALLOWED, do not affect exit code).
const real = [];
const allowed = [];
for (const [field, en, pt] of pairs) {
if (!same(en, pt)) continue;
const key = `${collection}${collectionFile}${field}`;
if (allowlist.has(key)) {
allowed.push([field, en, allowlistReasons.get(key)]);
} else {
real.push([field, en, null]);
}
}
totalLocalized += pairs.length;
if (real.length > 0) {
totalReal += real.length;
if (!groups.has(collection)) groups.set(collection, []);
groups.get(collection).push({ file: filename, pairs: real });
}
if (allowed.length > 0) {
totalAllowed += allowed.length;
if (!allowedGroups.has(collection)) allowedGroups.set(collection, []);
allowedGroups.get(collection).push({ file: filename, pairs: allowed });
}
} }
if (groups.size === 0) { const printGroup = (entries, label) => {
for (const [collection, list] of entries) {
console.log(`\n[${collection}]`);
for (const { file, pairs } of list) {
console.log(` ${file}`);
for (const [field, en, reason] of pairs) {
const sample = typeof en === 'string' ? JSON.stringify(en).slice(0, 80) : '<non-string>';
const suffix = reason ? ` [${label}: ${reason}]` : '';
console.log(` - ${field.padEnd(28)} ${sample}${suffix}`);
}
}
}
};
// Clean case: no identicals at all.
if (totalReal === 0 && totalAllowed === 0) {
console.log('OK: no identical en/pt pairs found under', ROOT); console.log('OK: no identical en/pt pairs found under', ROOT);
process.exit(0); process.exit(0);
} }
// Print grouped report. // Show allowed entries first, then real offenders (if any).
for (const [collection, entries] of groups) { printGroup(allowedGroups, 'ALLOWED');
console.log(`\n[${collection}]`);
for (const { file, pairs } of entries) { if (totalReal > 0) {
console.log(` ${file}`); printGroup(groups, 'REAL');
for (const [field, en, pt] of pairs) { console.log(
const sample = typeof en === 'string' ? JSON.stringify(en).slice(0, 80) : '<non-string>'; `\nFAIL: ${totalReal} unallowed identical localized field(s) across ${groups.size} collection(s) of ${ROOT}`,
console.log(` - ${field.padEnd(28)} ${sample}`); );
} console.log(
} 'A `pt` identical to `en` is how a bilingual site becomes monolingual. Translate, then re-run.',
);
process.exit(1);
} }
console.log( console.log(`\nOK: ${totalAllowed} identical field(s) found, all on the allowlist.`);
`\nFAIL: ${totalIdentical} identical localized field(s) across ${groups.size} collection(s) of ${ROOT}`, process.exit(0);
);
console.log(
'A `pt` identical to `en` is how a bilingual site becomes monolingual. Translate, then re-run.',
);
process.exit(1);
+1 -1
View File
@@ -9,7 +9,7 @@
"check": "astro check", "check": "astro check",
"lint": "eslint . --max-warnings=0 && stylelint --allow-empty-input 'src/**/*.css' --max-warnings=0", "lint": "eslint . --max-warnings=0 && stylelint --allow-empty-input 'src/**/*.css' --max-warnings=0",
"format": "prettier --write .", "format": "prettier --write .",
"verify": "node scripts/verify.mjs && node scripts/audit-ui.mjs && node .agents/scripts/check-tokens.mjs", "verify": "node .agents/scripts/audit-translations.mjs && node scripts/verify.mjs && node scripts/audit-ui.mjs && node .agents/scripts/check-tokens.mjs",
"gate": "./.agents/scripts/gate.sh", "gate": "./.agents/scripts/gate.sh",
"snapshot": "node .agents/scripts/snapshot-route.mjs", "snapshot": "node .agents/scripts/snapshot-route.mjs",
"prepare": "husky" "prepare": "husky"
+7 -5
View File
@@ -271,11 +271,13 @@ if (!allPages.every(([, page]) => page.includes('name="viewport"')))
throw new Error('a built route lacks a viewport declaration'); throw new Error('a built route lacks a viewport declaration');
if (allPages.some(([, page]) => /<(script|link)[^>]+(src|href)="https?:[^\"]+"/i.test(page))) if (allPages.some(([, page]) => /<(script|link)[^>]+(src|href)="https?:[^\"]+"/i.test(page)))
throw new Error('a built route has an external runtime dependency'); throw new Error('a built route has an external runtime dependency');
if ( // `pnpm run verify` may now prepend `node .agents/scripts/audit-translations.mjs &&`
!read('package.json').includes( // for fail-fast translation checks. Allow an optional audit-translations prefix
'"verify": "node scripts/verify.mjs && node scripts/audit-ui.mjs && node .agents/scripts/check-tokens.mjs"', // while still requiring the three core scripts in order.
) const verifyChain = read('package.json');
) const verifyShape =
/\"verify\":\s*\"(?:node \.agents\/scripts\/audit-translations\.mjs && )?node scripts\/verify\.mjs && node scripts\/audit-ui\.mjs && node \.agents\/scripts\/check-tokens\.mjs\"/;
if (!verifyShape.test(verifyChain))
throw new Error('pnpm verify no longer runs audit-ui and check-tokens'); throw new Error('pnpm verify no longer runs audit-ui and check-tokens');
if (!read('.agents/scripts/gate.sh').includes('pnpm run verify')) if (!read('.agents/scripts/gate.sh').includes('pnpm run verify'))
throw new Error('the gate no longer runs the output contract'); throw new Error('the gate no longer runs the output contract');
+23 -23
View File
@@ -2,57 +2,57 @@
"id": "agents", "id": "agents",
"eyebrow": { "eyebrow": {
"en": "Subagent workflow", "en": "Subagent workflow",
"pt": "Subagent workflow" "pt": "Fluxo de subagentes"
}, },
"title": { "title": {
"en": "One branch<br>per <em>hand.</em>", "en": "One branch<br>per <em>hand.</em>",
"pt": "One branch<br>per <em>hand.</em>" "pt": "Uma branch<br>por <em>mão.</em>"
}, },
"lede": { "lede": {
"en": "Agents work when roles, files, and evidence are bounded. A worktree gives each worker its own checkout while the orchestrator protects intent.", "en": "Agents work when roles, files, and evidence are bounded. A worktree gives each worker its own checkout while the orchestrator protects intent.",
"pt": "Agents work when roles, files, and evidence are bounded. A worktree gives each worker its own checkout while the orchestrator protects intent." "pt": "Agentes funcionam quando papéis, arquivos e evidências são delimitados. Um worktree dá a cada agente seu próprio checkout enquanto o orquestrador protege a intenção."
}, },
"cards": [ "cards": [
{ {
"label": { "label": {
"en": "FRAME", "en": "FRAME",
"pt": "FRAME" "pt": "ENQUADRAR"
}, },
"title": { "title": {
"en": "Orchestrator", "en": "Orchestrator",
"pt": "Orchestrator" "pt": "Orquestrador"
}, },
"copy": { "copy": {
"en": "Owns scope, task graph, boundaries, and integration.", "en": "Owns scope, task graph, boundaries, and integration.",
"pt": "Owns scope, task graph, boundaries, and integration." "pt": "Dono do escopo, do grafo de tarefas, das fronteiras e da integração."
} }
}, },
{ {
"label": { "label": {
"en": "HAND OFF", "en": "HAND OFF",
"pt": "HAND OFF" "pt": "PASSAR"
}, },
"title": { "title": {
"en": "Worker", "en": "Worker",
"pt": "Worker" "pt": "Agente"
}, },
"copy": { "copy": {
"en": "Owns one coherent slice and one worktree.", "en": "Owns one coherent slice and one worktree.",
"pt": "Owns one coherent slice and one worktree." "pt": "Dono de uma fatia coerente e de um worktree."
} }
}, },
{ {
"label": { "label": {
"en": "PROVE", "en": "PROVE",
"pt": "PROVE" "pt": "COMPROVAR"
}, },
"title": { "title": {
"en": "Verifier", "en": "Verifier",
"pt": "Verifier" "pt": "Verificador"
}, },
"copy": { "copy": {
"en": "Re-runs gates and reports remaining gaps.", "en": "Re-runs gates and reports remaining gaps.",
"pt": "Re-runs gates and reports remaining gaps." "pt": "Roda gates novamente e reporta o que ainda falta."
} }
} }
], ],
@@ -60,29 +60,29 @@
{ {
"eyebrow": { "eyebrow": {
"en": "The tree", "en": "The tree",
"pt": "The tree" "pt": "A árvore"
}, },
"title": { "title": {
"en": "Split at<br>the <em>seam.</em>", "en": "Split at<br>the <em>seam.</em>",
"pt": "Split at<br>the <em>seam.</em>" "pt": "Divida na<br><em>costura.</em>"
}, },
"panelLabel": { "panelLabel": {
"en": "MAIN / ORCHESTRATOR", "en": "MAIN / ORCHESTRATOR",
"pt": "MAIN / ORCHESTRATOR" "pt": "MAIN / ORQUESTRADOR"
}, },
"panelCode": { "panelCode": {
"en": "├── agent/ui → components + visual states\n├── agent/tests → acceptance + regressions\n└── agent/docs → guide + examples\n\nmerge after each leaf returns a diff and evidence", "en": "├── agent/ui → components + visual states\n├── agent/tests → acceptance + regressions\n└── agent/docs → guide + examples\n\nmerge after each leaf returns a diff and evidence",
"pt": "├── agent/ui → components + visual states\n├── agent/tests → acceptance + regressions\n└── agent/docs → guide + examples\n\nmerge after each leaf returns a diff and evidence" "pt": "├── agent/ui → componentes + estados visuais\n├── agent/tests → aceitação + regressões\n└── agent/docs → guia + exemplos\n\nfaça merge depois que cada folha devolver um diff e evidências"
} }
}, },
{ {
"eyebrow": { "eyebrow": {
"en": "Handoff", "en": "Handoff",
"pt": "Handoff" "pt": "Passagem"
}, },
"title": { "title": {
"en": "Context that<br>can <em>travel.</em>", "en": "Context that<br>can <em>travel.</em>",
"pt": "Context that<br>can <em>travel.</em>" "pt": "Contexto que<br>pode <em>viajar.</em>"
}, },
"steps": [ "steps": [
{ {
@@ -92,27 +92,27 @@
}, },
"copy": { "copy": {
"en": "Goal, owned files, dependencies, non-goals, acceptance.", "en": "Goal, owned files, dependencies, non-goals, acceptance.",
"pt": "Goal, owned files, dependencies, non-goals, acceptance." "pt": "Objetivo, arquivos sob sua posse, dependências, fora de escopo, aceitação."
} }
}, },
{ {
"label": { "label": {
"en": "Isolation", "en": "Isolation",
"pt": "Isolation" "pt": "Isolamento"
}, },
"copy": { "copy": {
"en": "One branch and worktree per independent change.", "en": "One branch and worktree per independent change.",
"pt": "One branch and worktree per independent change." "pt": "Uma branch e um worktree por mudança independente."
} }
}, },
{ {
"label": { "label": {
"en": "Evidence", "en": "Evidence",
"pt": "Evidence" "pt": "Evidência"
}, },
"copy": { "copy": {
"en": "Commands, result, changed files, screenshots, gaps.", "en": "Commands, result, changed files, screenshots, gaps.",
"pt": "Commands, result, changed files, screenshots, gaps." "pt": "Comandos, resultado, arquivos alterados, capturas de tela, lacunas."
} }
} }
] ]
+29 -23
View File
@@ -1,83 +1,89 @@
{ {
"id": "landing", "id": "landing",
"eyebrow": { "en": "The short route", "pt": "The short route" }, "eyebrow": {
"title": { "en": "Ship the<br><em>system.</em>", "pt": "Ship the<br><em>system.</em>" }, "en": "The short route",
"pt": "A rota curta"
},
"title": {
"en": "Ship the<br><em>system.</em>",
"pt": "Entregue o<br><em>sistema.</em>"
},
"lede": { "lede": {
"en": "Start with the map. Then open the one chapter that matches the decision in front of you: model, agent, worktree, skill, rule, or proof.", "en": "Start with the map. Then open the one chapter that matches the decision in front of you: model, agent, worktree, skill, rule, or proof.",
"pt": "Start with the map. Then open the one chapter that matches the decision in front of you: model, agent, worktree, skill, rule, or proof." "pt": "Comece pelo mapa. Depois abra o capítulo que combina com a decisão à sua frente: modelo, agente, worktree, skill, regra ou prova."
}, },
"threadLabel": { "threadLabel": {
"en": "THE THREAD", "en": "THE THREAD",
"pt": "THE THREAD" "pt": "O FIO"
}, },
"threadText": { "threadText": {
"en": "Frame uncertainty → isolate execution → preserve judgment → verify the change.", "en": "Frame uncertainty → isolate execution → preserve judgment → verify the change.",
"pt": "Frame uncertainty → isolate execution → preserve judgment → verify the change." "pt": "Enquadre a incerteza → isole a execução → preserve o julgamento → verifique a mudança."
}, },
"footer": { "footer": {
"en": "The route map is now the default entry. The full guide remains available whenever you want the whole narrative.", "en": "The route map is now the default entry. The full guide remains available whenever you want the whole narrative.",
"pt": "The route map is now the default entry. The full guide remains available whenever you want the whole narrative." "pt": "O mapa de rotas é agora a entrada padrão. O guia completo segue disponível sempre que você quiser a narrativa inteira."
}, },
"cards": [ "cards": [
{ {
"label": { "en": "01", "pt": "01" }, "label": { "en": "01", "pt": "01" },
"title": { "en": "Models", "pt": "Models" }, "title": { "en": "Models", "pt": "Modelos" },
"copy": { "copy": {
"en": "Capability and effort are separate knobs.", "en": "Capability and effort are separate knobs.",
"pt": "Capability and effort are separate knobs." "pt": "Capacidade e esforço são controles separados."
}, },
"href": "models/", "href": "models/",
"cta": { "en": "Open chapter →", "pt": "Open chapter →" } "cta": { "en": "Open chapter →", "pt": "Abrir capítulo →" }
}, },
{ {
"label": { "en": "02", "pt": "02" }, "label": { "en": "02", "pt": "02" },
"title": { "en": "Agents & trees", "pt": "Agents & trees" }, "title": { "en": "Agents & trees", "pt": "Agentes e árvores" },
"copy": { "copy": {
"en": "Bound roles, handoffs, and worktrees.", "en": "Bound roles, handoffs, and worktrees.",
"pt": "Bound roles, handoffs, and worktrees." "pt": "Limite papéis, handoffs e worktrees."
}, },
"href": "agents/", "href": "agents/",
"cta": { "en": "Open chapter →", "pt": "Open chapter →" } "cta": { "en": "Open chapter →", "pt": "Abrir capítulo →" }
}, },
{ {
"label": { "en": "03", "pt": "03" }, "label": { "en": "03", "pt": "03" },
"title": { "en": "Skills", "pt": "Skills" }, "title": { "en": "Skills", "pt": "Skills" },
"copy": { "copy": {
"en": "Capture repeatable decisions in small packages.", "en": "Capture repeatable decisions in small packages.",
"pt": "Capture repeatable decisions in small packages." "pt": "Capture decisões repetíveis em pacotes pequenos."
}, },
"href": "skills/", "href": "skills/",
"cta": { "en": "Open chapter →", "pt": "Open chapter →" } "cta": { "en": "Open chapter →", "pt": "Abrir capítulo →" }
}, },
{ {
"label": { "en": "04", "pt": "04" }, "label": { "en": "04", "pt": "04" },
"title": { "en": "Rules", "pt": "Rules" }, "title": { "en": "Rules", "pt": "Regras" },
"copy": { "copy": {
"en": "Connect guidance to enforcement.", "en": "Connect guidance to enforcement.",
"pt": "Connect guidance to enforcement." "pt": "Conecte orientação a enforcement."
}, },
"href": "rules/", "href": "rules/",
"cta": { "en": "Open chapter →", "pt": "Open chapter →" } "cta": { "en": "Open chapter →", "pt": "Abrir capítulo →" }
}, },
{ {
"label": { "en": "05", "pt": "05" }, "label": { "en": "05", "pt": "05" },
"title": { "en": "Hands-on", "pt": "Hands-on" }, "title": { "en": "Hands-on", "pt": "Prática" },
"copy": { "copy": {
"en": "Compare a strong prompt with skill-enabled work.", "en": "Compare a strong prompt with skill-enabled work.",
"pt": "Compare a strong prompt with skill-enabled work." "pt": "Compare um prompt forte com trabalho assistido por skills."
}, },
"href": "hands-on/starter/", "href": "hands-on/starter/",
"cta": { "en": "Open lab →", "pt": "Open lab →" } "cta": { "en": "Open lab →", "pt": "Abrir lab →" }
}, },
{ {
"label": { "en": "06", "pt": "06" }, "label": { "en": "06", "pt": "06" },
"title": { "en": "Review desk", "pt": "Review desk" }, "title": { "en": "Review desk", "pt": "Mesa de revisão" },
"copy": { "copy": {
"en": "Browse original packages, references, scripts, and improvements.", "en": "Browse original packages, references, scripts, and improvements.",
"pt": "Browse original packages, references, scripts, and improvements." "pt": "Explore pacotes originais, referências, scripts e melhorias."
}, },
"href": "skills-review/", "href": "skills-review/",
"cta": { "en": "Open desk →", "pt": "Open desk →" } "cta": { "en": "Open desk →", "pt": "Abrir mesa →" }
} }
] ]
} }
+24 -24
View File
@@ -2,57 +2,57 @@
"id": "models", "id": "models",
"eyebrow": { "eyebrow": {
"en": "Model routing", "en": "Model routing",
"pt": "Model routing" "pt": "Roteamento de modelos"
}, },
"title": { "title": {
"en": "Choose the<br><em>engine.</em>", "en": "Choose the<br><em>engine.</em>",
"pt": "Choose the<br><em>engine.</em>" "pt": "Escolha o<br><em>motor.</em>"
}, },
"lede": { "lede": {
"en": "A model has a capability ceiling. Effort controls how much room it gets to reason. Route by uncertainty and verification cost.", "en": "A model has a capability ceiling. Effort controls how much room it gets to reason. Route by uncertainty and verification cost.",
"pt": "A model has a capability ceiling. Effort controls how much room it gets to reason. Route by uncertainty and verification cost." "pt": "Um modelo tem um teto de capacidade. O esforço controla quanto espaço ele ganha para raciocinar. Roteie por incerteza e custo de verificação."
}, },
"cards": [ "cards": [
{ {
"label": { "label": {
"en": "LOW", "en": "LOW",
"pt": "LOW" "pt": "BAIXO"
}, },
"title": { "title": {
"en": "Bounded rhythm", "en": "Bounded rhythm",
"pt": "Bounded rhythm" "pt": "Ritmo delimitado"
}, },
"copy": { "copy": {
"en": "Lookup, small edits, formatting, and transformations with clear checks.", "en": "Lookup, small edits, formatting, and transformations with clear checks.",
"pt": "Lookup, small edits, formatting, and transformations with clear checks." "pt": "Consultas, edições pequenas, formatação e transformações com checagens claras."
} }
}, },
{ {
"label": { "label": {
"en": "MEDIUM", "en": "MEDIUM",
"pt": "MEDIUM" "pt": "MÉDIO"
}, },
"title": { "title": {
"en": "Default work", "en": "Default work",
"pt": "Default work" "pt": "Trabalho padrão"
}, },
"copy": { "copy": {
"en": "Normal implementation where the contract is clear but context matters.", "en": "Normal implementation where the contract is clear but context matters.",
"pt": "Normal implementation where the contract is clear but context matters." "pt": "Implementação normal em que o contrato é claro, mas o contexto importa."
} }
}, },
{ {
"label": { "label": {
"en": "HIGH", "en": "HIGH",
"pt": "HIGH" "pt": "ALTO"
}, },
"title": { "title": {
"en": "Ambiguity", "en": "Ambiguity",
"pt": "Ambiguity" "pt": "Ambiguidade"
}, },
"copy": { "copy": {
"en": "Planning, architecture, security judgment, and hard failures.", "en": "Planning, architecture, security judgment, and hard failures.",
"pt": "Planning, architecture, security judgment, and hard failures." "pt": "Planejamento, arquitetura, julgamento de segurança e falhas difíceis."
} }
} }
], ],
@@ -60,59 +60,59 @@
{ {
"eyebrow": { "eyebrow": {
"en": "Two knobs", "en": "Two knobs",
"pt": "Two knobs" "pt": "Dois controles"
}, },
"title": { "title": {
"en": "Capability<br>× effort", "en": "Capability<br>× effort",
"pt": "Capability<br>× effort" "pt": "Capacidade<br>× esforço"
}, },
"panelLabel": { "panelLabel": {
"en": "ROUTING RULE", "en": "ROUTING RULE",
"pt": "ROUTING RULE" "pt": "REGRA DE ROTEAMENTO"
}, },
"panelCode": { "panelCode": {
"en": "strong model + high effort → frame ambiguity\nlight model + low effort → bounded execution\nraise one knob at a time → compare evidence", "en": "strong model + high effort → frame ambiguity\nlight model + low effort → bounded execution\nraise one knob at a time → compare evidence",
"pt": "strong model + high effort → frame ambiguity\nlight model + low effort → bounded execution\nraise one knob at a time → compare evidence" "pt": "modelo forte + esforço alto → enquadrar ambiguidade\nmodelo leve + esforço baixo → execução delimitada\nsuba um controle por vez → compare evidências"
} }
}, },
{ {
"eyebrow": { "eyebrow": {
"en": "Sequence", "en": "Sequence",
"pt": "Sequence" "pt": "Sequência"
}, },
"title": { "title": {
"en": "Spend judgment<br>where it <em>compounds.</em>", "en": "Spend judgment<br>where it <em>compounds.</em>",
"pt": "Spend judgment<br>where it <em>compounds.</em>" "pt": "Invista julgamento<br>onde ele <em>compensa.</em>"
}, },
"steps": [ "steps": [
{ {
"label": { "label": {
"en": "Plan", "en": "Plan",
"pt": "Plan" "pt": "Planejar"
}, },
"copy": { "copy": {
"en": "Strong model: scope, risks, acceptance, and worktree split.", "en": "Strong model: scope, risks, acceptance, and worktree split.",
"pt": "Strong model: scope, risks, acceptance, and worktree split." "pt": "Modelo forte: escopo, riscos, aceitação e divisão de worktrees."
} }
}, },
{ {
"label": { "label": {
"en": "Build", "en": "Build",
"pt": "Build" "pt": "Construir"
}, },
"copy": { "copy": {
"en": "Focused worker: smallest context and lightest model that can pass.", "en": "Focused worker: smallest context and lightest model that can pass.",
"pt": "Focused worker: smallest context and lightest model that can pass." "pt": "Worker focado: o menor contexto e o modelo mais leve que passa."
} }
}, },
{ {
"label": { "label": {
"en": "Review", "en": "Review",
"pt": "Review" "pt": "Revisar"
}, },
"copy": { "copy": {
"en": "Independent pass when missed issues cost more than the call.", "en": "Independent pass when missed issues cost more than the call.",
"pt": "Independent pass when missed issues cost more than the call." "pt": "Revisão independente quando erros perdidos custam mais que a chamada."
} }
} }
] ]
+16 -16
View File
@@ -1,56 +1,56 @@
{ {
"id": "skills", "id": "skills",
"eyebrow": { "en": "Reusable judgment", "pt": "Reusable judgment" }, "eyebrow": { "en": "Reusable judgment", "pt": "Julgamento reutilizável" },
"title": { "en": "Teach the<br><em>decision.</em>", "pt": "Teach the<br><em>decision.</em>" }, "title": { "en": "Teach the<br><em>decision.</em>", "pt": "Ensine a<br><em>decisão.</em>" },
"lede": { "lede": {
"en": "A skill changes behavior. Keep the trigger precise, put the workflow in <code>SKILL.md</code>, and move conditional facts, scripts, and examples into focused files.", "en": "A skill changes behavior. Keep the trigger precise, put the workflow in <code>SKILL.md</code>, and move conditional facts, scripts, and examples into focused files.",
"pt": "A skill changes behavior. Keep the trigger precise, put the workflow in <code>SKILL.md</code>, and move conditional facts, scripts, and examples into focused files." "pt": "Uma skill muda comportamento. Mantenha o gatilho preciso, coloque o workflow em <code>SKILL.md</code> e mova fatos condicionais, scripts e exemplos para arquivos focados."
}, },
"sections": [ "sections": [
{ {
"eyebrow": { "en": "Package anatomy", "pt": "Package anatomy" }, "eyebrow": { "en": "Package anatomy", "pt": "Anatomia do pacote" },
"title": { "title": {
"en": "One job.<br>More than<br>one <em>file.</em>", "en": "One job.<br>More than<br>one <em>file.</em>",
"pt": "One job.<br>More than<br>one <em>file.</em>" "pt": "Um trabalho.<br>Mais que<br>um <em>arquivo.</em>"
}, },
"copy": { "copy": {
"en": "Choose a file to see why it belongs in the package.", "en": "Choose a file to see why it belongs in the package.",
"pt": "Choose a file to see why it belongs in the package." "pt": "Escolha um arquivo para ver por que ele pertence ao pacote."
} }
}, },
{ {
"eyebrow": { "en": "Create a skill", "pt": "Create a skill" }, "eyebrow": { "en": "Create a skill", "pt": "Crie uma skill" },
"title": { "title": {
"en": "Observe →<br>trigger →<br>validate", "en": "Observe →<br>trigger →<br>validate",
"pt": "Observe →<br>trigger →<br>validate" "pt": "Observe →<br>defina o gatilho →<br>valide"
}, },
"steps": [ "steps": [
{ {
"label": { "en": "Observe friction", "pt": "Observe friction" }, "label": { "en": "Observe friction", "pt": "Observe o atrito" },
"copy": { "copy": {
"en": "Find a repeated decision or failure.", "en": "Find a repeated decision or failure.",
"pt": "Find a repeated decision or failure." "pt": "Encontre uma decisão ou falha repetida."
} }
}, },
{ {
"label": { "en": "Define the trigger", "pt": "Define the trigger" }, "label": { "en": "Define the trigger", "pt": "Defina o gatilho" },
"copy": { "copy": {
"en": "Say when it should load and when it should stay out.", "en": "Say when it should load and when it should stay out.",
"pt": "Say when it should load and when it should stay out." "pt": "Diga quando deve carregar e quando deve ficar de fora."
} }
}, },
{ {
"label": { "en": "Choose anatomy", "pt": "Choose anatomy" }, "label": { "en": "Choose anatomy", "pt": "Escolha a anatomia" },
"copy": { "copy": {
"en": "Use references for facts and scripts for deterministic mechanics.", "en": "Use references for facts and scripts for deterministic mechanics.",
"pt": "Use references for facts and scripts for deterministic mechanics." "pt": "Use referências para fatos e scripts para mecânicas determinísticas."
} }
}, },
{ {
"label": { "en": "Evaluate behavior", "pt": "Evaluate behavior" }, "label": { "en": "Evaluate behavior", "pt": "Avalie o comportamento" },
"copy": { "copy": {
"en": "Test realistic prompts, edge cases, safety, and evidence.", "en": "Test realistic prompts, edge cases, safety, and evidence.",
"pt": "Test realistic prompts, edge cases, safety, and evidence." "pt": "Teste prompts realistas, casos extremos, segurança e evidência."
} }
} }
] ]
+88 -28
View File
@@ -1,75 +1,135 @@
{ {
"id": "summary", "id": "summary",
"eyebrow": { "en": "Start here", "pt": "Start here" }, "eyebrow": {
"title": { "en": "Ship the<br><em>system.</em>", "pt": "Ship the<br><em>system.</em>" }, "en": "Start here",
"pt": "Comece aqui"
},
"title": {
"en": "Ship the<br><em>system.</em>",
"pt": "Entregue o<br><em>sistema.</em>"
},
"lede": { "lede": {
"en": "This guide turns AI work into a shape: frame the problem, choose the model and agent, isolate changes, teach repeatable decisions, and verify the result.", "en": "This guide turns AI work into a shape: frame the problem, choose the model and agent, isolate changes, teach repeatable decisions, and verify the result.",
"pt": "This guide turns AI work into a shape: frame the problem, choose the model and agent, isolate changes, teach repeatable decisions, and verify the result." "pt": "Este guia transforma trabalho com IA em uma forma: enquadre o problema, escolha o modelo e o agente, isole mudanças, ensine decisões repetíveis e verifique o resultado."
}, },
"footer": { "footer": {
"en": "Each chapter stands alone; the order follows a real task becoming a reliable change.", "en": "Each chapter stands alone; the order follows a real task becoming a reliable change.",
"pt": "Each chapter stands alone; the order follows a real task becoming a reliable change." "pt": "Cada capítulo se sustenta sozinho; a ordem segue uma tarefa real se tornando uma mudança confiável."
}, },
"cards": [ "cards": [
{ {
"label": { "en": "01", "pt": "01" }, "label": {
"title": { "en": "Models", "pt": "Models" }, "en": "01",
"pt": "01"
},
"title": {
"en": "Models",
"pt": "Modelos"
},
"copy": { "copy": {
"en": "Capability and effort are separate knobs.", "en": "Capability and effort are separate knobs.",
"pt": "Capability and effort are separate knobs." "pt": "Capacidade e esforço são controles separados."
}, },
"href": "../models/", "href": "../models/",
"cta": { "en": "Open chapter →", "pt": "Open chapter →" } "cta": {
"en": "Open chapter →",
"pt": "Abrir capítulo →"
}
}, },
{ {
"label": { "en": "02", "pt": "02" }, "label": {
"title": { "en": "Agents & trees", "pt": "Agents & trees" }, "en": "02",
"pt": "02"
},
"title": {
"en": "Agents & trees",
"pt": "Agentes e árvores"
},
"copy": { "copy": {
"en": "Bound roles, handoffs, and worktrees.", "en": "Bound roles, handoffs, and worktrees.",
"pt": "Bound roles, handoffs, and worktrees." "pt": "Limite papéis, handoffs e worktrees."
}, },
"href": "../agents/", "href": "../agents/",
"cta": { "en": "Open chapter →", "pt": "Open chapter →" } "cta": {
"en": "Open chapter →",
"pt": "Abrir capítulo →"
}
}, },
{ {
"label": { "en": "03", "pt": "03" }, "label": {
"title": { "en": "Skills", "pt": "Skills" }, "en": "03",
"pt": "03"
},
"title": {
"en": "Skills",
"pt": "Skills"
},
"copy": { "copy": {
"en": "Capture repeatable decisions.", "en": "Capture repeatable decisions.",
"pt": "Capture repeatable decisions." "pt": "Capture decisões repetíveis."
}, },
"href": "../skills/", "href": "../skills/",
"cta": { "en": "Open chapter →", "pt": "Open chapter →" } "cta": {
"en": "Open chapter →",
"pt": "Abrir capítulo →"
}
}, },
{ {
"label": { "en": "04", "pt": "04" }, "label": {
"title": { "en": "Rules", "pt": "Rules" }, "en": "04",
"pt": "04"
},
"title": {
"en": "Rules",
"pt": "Regras"
},
"copy": { "copy": {
"en": "Connect guidance to enforcement.", "en": "Connect guidance to enforcement.",
"pt": "Connect guidance to enforcement." "pt": "Conecte orientação a enforcement."
}, },
"href": "../rules/", "href": "../rules/",
"cta": { "en": "Open chapter →", "pt": "Open chapter →" } "cta": {
"en": "Open chapter →",
"pt": "Abrir capítulo →"
}
}, },
{ {
"label": { "en": "05", "pt": "05" }, "label": {
"title": { "en": "Practice", "pt": "Practice" }, "en": "05",
"pt": "05"
},
"title": {
"en": "Practice",
"pt": "Prática"
},
"copy": { "copy": {
"en": "Compare prompts and skill-enabled runs.", "en": "Compare prompts and skill-enabled runs.",
"pt": "Compare prompts and skill-enabled runs." "pt": "Compare prompts e execuções com skills."
}, },
"href": "../hands-on/starter/", "href": "../hands-on/starter/",
"cta": { "en": "Open lab →", "pt": "Open lab →" } "cta": {
"en": "Open lab →",
"pt": "Abrir lab →"
}
}, },
{ {
"label": { "en": "06", "pt": "06" }, "label": {
"title": { "en": "Review desk", "pt": "Review desk" }, "en": "06",
"pt": "06"
},
"title": {
"en": "Review desk",
"pt": "Mesa de revisão"
},
"copy": { "copy": {
"en": "Browse original files and improved drafts.", "en": "Browse original files and improved drafts.",
"pt": "Browse original files and improved drafts." "pt": "Explore arquivos originais e rascunhos melhorados."
}, },
"href": "../skills-review/", "href": "../skills-review/",
"cta": { "en": "Open desk →", "pt": "Open desk →" } "cta": {
"en": "Open desk →",
"pt": "Abrir mesa →"
}
} }
] ]
} }