feat: assemble astro full guide

This commit is contained in:
Marcos Paulo
2026-09-05 20:05:52 +00:00
parent 98ab6db3de
commit 677c511979
+597
View File
@@ -0,0 +1,597 @@
---
// /full-guide/ — assembled from typed guide collections and the task 10 blocks.
// This route deliberately never imports the legacy full-guide HTML: task 20 removes
// that tree, and both locales must be present in the server-rendered document.
import { getCollection } from 'astro:content';
import BaseLayout from '../layouts/BaseLayout.astro';
import FleetDiagram from '../components/blocks/FleetDiagram.astro';
import HandoffTable from '../components/blocks/HandoffTable.astro';
import PhasePanel from '../components/blocks/PhasePanel.astro';
import RouteTable from '../components/blocks/RouteTable.astro';
import SkillPackage from '../components/blocks/SkillPackage.astro';
import WorktreeMap from '../components/blocks/WorktreeMap.astro';
import CopyPrompt from '../components/islands/CopyPrompt.astro';
import GuideSelector from '../components/islands/GuideSelector.astro';
import LanguageToggle from '../components/islands/LanguageToggle.astro';
import ReadingProgress from '../components/islands/ReadingProgress.astro';
import '../../styles.css';
import '../../responsive.css';
import '../../full-guide/audit.css';
type Entry<T extends { id: string }> = { data: T };
const toRecord = <T extends { id: string }>(entries: Entry<T>[]) =>
Object.fromEntries(entries.map(({ data }) => [data.id, data]));
const [
phaseEntries,
workerEntries,
treeEntries,
routeEntries,
providerEntries,
effortEntries,
skillFileEntries,
workflowEntries,
commonSkillEntries,
promptEntries,
installEntries,
] = await Promise.all([
getCollection('phases'),
getCollection('workers'),
getCollection('trees'),
getCollection('routes'),
getCollection('providers'),
getCollection('efforts'),
getCollection('skillFiles'),
getCollection('skillWorkflow'),
getCollection('commonSkills'),
getCollection('handsOnPrompts'),
getCollection('skillInstallPrompts'),
]);
const phases = toRecord(phaseEntries);
const workers = toRecord(workerEntries);
const trees = toRecord(treeEntries);
const routes = toRecord(routeEntries);
const providers = toRecord(providerEntries);
const efforts = toRecord(effortEntries);
const skillFiles = toRecord(skillFileEntries);
const skillWorkflow = toRecord(workflowEntries);
const commonSkills = toRecord(commonSkillEntries);
const handsOn = promptEntries.find(({ data }) => data.id === 'tiny-tasks')?.data;
const install = installEntries.find(({ data }) => data.id === 'install')?.data;
if (!handsOn || !install) throw new Error('full-guide content collections are incomplete');
// Selector chrome is page-specific, so it remains an inline bilingual constant.
const labels = {
context: { en: 'context: isolated', pt: 'contexto: isolado' },
owner: { en: 'OWNER', pt: 'RESPONSÁVEL' },
reasoningLoad: { en: 'REASONING LOAD', pt: 'CARGA DE RACIOCÍNIO' },
officialSource: { en: 'OFFICIAL SOURCE ↗', pt: 'FONTE OFICIAL ↗' },
skillFileHint: {
en: 'select another file to explore',
pt: 'clique em outro arquivo para explorar',
},
workflow: {
question: { en: 'QUESTION', pt: 'PERGUNTA' },
action: { en: 'ACTION', pt: 'AÇÃO' },
artifact: { en: 'ARTIFACT', pt: 'ARTEFATO' },
proof: { en: 'PROOF', pt: 'PROVA' },
},
commonSkill: {
whenToUse: { en: 'WHEN TO USE', pt: 'QUANDO USAR' },
example: { en: 'EXAMPLE', pt: 'EXEMPLO' },
watchOut: { en: 'WATCH OUT', pt: 'CUIDADO' },
source: { en: 'GITHUB SOURCE ↗', pt: 'FONTE NO GITHUB ↗' },
},
};
const selectorData = {
phases,
workers,
trees,
routes,
providers,
efforts,
skillFiles,
skillWorkflow,
commonSkills,
labels,
};
const workerCards = [
{ id: 'ui', label: 'UI', strong: 'Component and visual states', code: 'agent/ui' },
{ id: 'tests', label: 'TEST', strong: 'Acceptance cases', code: 'agent/tests' },
{ id: 'docs', label: 'DOCS', strong: 'Guide and examples', code: 'agent/docs' },
];
const treeBranches = [
{ id: 'ui', label: 'UI AGENT', strong: 'agent/ui', small: '3 files · working', tone: 'ui' },
{
id: 'tests',
label: 'TEST AGENT',
strong: 'agent/tests',
small: '8 checks · ready',
tone: 'tests',
},
{
id: 'docs',
label: 'DOCS AGENT',
strong: 'agent/docs',
small: '2 pages · review',
tone: 'docs',
},
];
const base = import.meta.env.BASE_URL;
---
<BaseLayout
title="AI For Dummies — Field Guide"
description="AI For Dummies: a field guide to skills, models, subagents, and worktrees."
>
<ReadingProgress />
<main id="full-guide">
<header class="topbar">
<a class="brand" href="#top"><span class="mark">A</span> field guide</a>
<nav class="chapter-links" aria-label="Chapter sections">
<a href="#fleet">01 fleet</a><a href="#worktrees">02 worktrees</a><a href="#models"
>03 models</a
><a href="#skills">04 skills</a><a href="#create-skill">05 create</a><a href="#field-kit"
>06 field kit</a
><a href="#hands-on">07 hands-on</a><a href="#verification">08 verify</a>
</nav>
<div class="topbar-tools">
<a class="skills-review-link" href={`${base}skills-review/`}>review submissions </a
><LanguageToggle /><span class="edition">AI ENGINEERING <i></i> 01 / 2026</span>
</div>
</header>
<section class="hero" id="top" data-language-content="en">
<div>
<p class="eyebrow">A presentation for humans who ship</p><h1>
AI for<br /><em>dummies.</em>
</h1><p class="lede">
You do not need an army of models. You need a system: one mind to frame the work, several
hands to execute it, and a clean boundary between every task.
</p>
</div><aside class="hero-index">
<span>FIELD NOTE / 001</span><strong>Ship the<br /><em>system.</em></strong><small
>Skills · agents · worktrees · proof</small>
</aside>
</section>
<section class="hero" id="top-pt" data-language-content="pt" hidden>
<div>
<p class="eyebrow">Uma apresentação para quem entrega software</p><h1>
IA para<br /><em>iniciantes.</em>
</h1><p class="lede">
Você não precisa de um exército de modelos. Precisa de um sistema: uma mente para
enquadrar o trabalho, várias mãos para executá-lo e uma fronteira clara entre cada tarefa.
</p>
</div><aside class="hero-index">
<span>NOTA DE CAMPO / 001</span><strong>Entregue o<br /><em>sistema.</em></strong><small
>Skills · agentes · worktrees · evidências</small>
</aside>
</section>
<section class="hero-stats" aria-label="Chapter summary" data-language-content="en">
<div><strong>01</strong><span>strong model<br />for ambiguity</span></div><div>
<strong>03</strong><span>bounded workers<br />in parallel</span>
</div><div><strong></strong><span>iterations<br />with evidence</span></div><p>
Read this as a route map, not a prompt recipe.
</p>
</section>
<section class="hero-stats" aria-label="Resumo dos capítulos" data-language-content="pt" hidden>
<div><strong>01</strong><span>modelo forte<br />para ambiguidade</span></div><div>
<strong>03</strong><span>workers delimitados<br />em paralelo</span>
</div><div><strong></strong><span>iterações<br />com evidências</span></div><p>
Leia isto como um mapa de rota, não como uma receita de prompt.
</p>
</section>
<section class="thesis" data-language-content="en">
<div>
<span>RULE ZERO</span><strong
>Strong model for ambiguity.<br />Light model for bounded work.</strong>
</div><div class="signal" aria-hidden="true">
<b>THINK</b><i></i><i></i><i></i><b>MAKE</b>
</div>
</section>
<section class="thesis" data-language-content="pt" hidden>
<div>
<span>REGRA ZERO</span><strong
>Modelo forte para ambiguidade.<br />Modelo leve para trabalho delimitado.</strong>
</div><div class="signal" aria-hidden="true">
<b>PENSE</b><i></i><i></i><i></i><b>FAÇA</b>
</div>
</section>
<section class="fleet" id="fleet">
<div class="section-label">
<span>A small fleet</span><span>coordination before parallelism</span>
</div><FleetDiagram
orchestrator={{
eyebrow: 'ORCHESTRATOR',
title: 'Decides what<br />needs to happen.',
code: 'Opus / reasoning',
}}
workers={workerCards}
/><div class="worker-detail" id="worker-detail" aria-live="polite">
<span>{workers.ui.en[0]}</span><strong>{workers.ui.en[1]}</strong><small
>{workers.ui.en[2]}</small>
</div><p class="caption">
The orchestrator preserves intent, writes small contracts, and gathers results that can be
verified. It does not need to type every line.
</p>
</section>
<section class="failure-map">
<div class="section-label">
<span>Why the boundary matters</span><span
>one vague task / three predictable failures</span>
</div><div class="failure-grid">
<article>
<span>01</span><strong>Context soup</strong><p>
Every worker reads everything. Nobody knows which facts are load-bearing.
</p>
</article><article>
<span>02</span><strong>Branch collision</strong><p>
Two agents touch the same checkout. The fastest path becomes conflict resolution.
</p>
</article><article>
<span>03</span><strong>Confident drift</strong><p>
The diff is polished, but no one checks whether it solved the original problem.
</p>
</article>
</div>
</section>
<section class="workflow" aria-labelledby="workflow-title">
<div class="copy">
<p class="eyebrow">The subagent loop</p><h2 id="workflow-title">
Click a phase.<br /><em>See the handoff.</em>
</h2><p>
Delegation means moving one bounded task into a smaller contextnot giving away
responsibility.
</p>
</div><PhasePanel
phases={[
{
id: 'plan',
label: 'PLAN',
number: '01',
title: phases.plan.title.en,
body: phases.plan.copy.en,
meta: { deliverable: phases.plan.model.en, gate: labels.context.en },
evidence: phases.plan.code.en,
},
{
id: 'build',
label: 'BUILD',
number: '02',
title: phases.build.title.en,
body: phases.build.copy.en,
meta: { deliverable: phases.build.model.en, gate: labels.context.en },
evidence: phases.build.code.en,
},
{
id: 'review',
label: 'REVIEW',
number: '03',
title: phases.review.title.en,
body: phases.review.copy.en,
meta: { deliverable: phases.review.model.en, gate: labels.context.en },
evidence: phases.review.code.en,
},
]}
/>
</section>
<section class="handoff">
<div class="section-label">
<span>What crosses contexts</span><span>brief diff evidence</span>
</div><HandoffTable
columns={['Package', 'Contains', 'Why it matters']}
rows={[
{
package: 'Brief',
contains: 'goal, files, boundaries',
why: 'stops the worker inventing the problem',
},
{
package: 'Worktree',
contains: 'branch and isolated checkout',
why: 'parallel edits do not collide',
},
{
package: 'Checks',
contains: 'tests, build, criteria',
why: 'turns “looks good” into evidence',
},
{
package: 'Diff',
contains: 'small, reviewable change',
why: 'integration and discard stay cheap',
},
]}
/>
</section>
<section class="worktrees" id="worktrees">
<div class="worktree-intro">
<p class="eyebrow">Git worktrees</p><h2>One branch<br />per <em>hand.</em></h2><p>
A worktree is another directory linked to the same repository. Each agent gets its own
checkout and index; history remains shared.
</p><p class="interaction-hint">
Select a node to inspect its checkout, owner, and next action.
</p>
</div><div class="tree-lab">
<div class="tree-toolbar">
<span>repository topology</span><span class="tree-live"><i></i> 4 checkouts</span>
</div><WorktreeMap branches={treeBranches} /><article
class="tree-detail"
id="tree-detail"
aria-live="polite"
>
<div><span>{labels.owner.en}</span><strong>{trees.main.owner.en}</strong></div><div>
<span>CHECKOUT</span><strong>{trees.main.path}</strong>
</div><p>{trees.main.note.en}</p><code>{trees.main.command}</code>
</article>
</div>
</section>
<section class="routing">
<div>
<p class="eyebrow">Model routing</p><h2>
Do not pay for<br />reasoning where<br />you need <em>rhythm.</em>
</h2><p class="interaction-hint">Choose a job to see why the model profile changes.</p>
</div><div class="route-console">
<RouteTable
routes={[
{
id: 'plan',
strong: 'Plan',
profile: 'strong / broad',
prompt: 'What changes? What can break?',
},
{
id: 'build',
strong: 'Build',
profile: 'fast / focused',
prompt: 'Implement this slice. Run these checks.',
},
{
id: 'explore',
strong: 'Explore',
profile: 'read-only / light',
prompt: 'Find where this contract is used.',
},
{
id: 'review',
strong: 'Review',
profile: 'independent',
prompt: 'Does the diff satisfy the brief?',
},
]}
/><article class="route-detail" id="route-detail" aria-live="polite">
<div class="route-meter"><span style={`--score:${routes.plan.score}%`}></span></div><div>
<small>{labels.reasoningLoad.en} · {routes.plan.score}</small><strong
>{routes.plan.label.en}</strong
><p>{routes.plan.why.en}</p>
</div>
</article>
</div>
</section>
<section class="model-gearbox" id="models">
<div class="section-label">
<span>Model gearbox</span><span>capability tier × thinking effort</span>
</div><div class="gearbox">
<div class="provider-tabs" role="tablist" aria-label="Model providers">
<button class="active" data-model-provider="openai" role="tab" aria-selected="true"
>OPENAI</button
><button data-model-provider="claude" role="tab" aria-selected="false">CLAUDE</button
><button data-model-provider="gemini" role="tab" aria-selected="false">GEMINI</button>
</div><article class="provider-detail" id="provider-detail" aria-live="polite">
<header>
<span>{providers.openai.label}</span><a
href={providers.openai.source}
target="_blank"
rel="noopener">{labels.officialSource.en}</a>
</header><h3>{providers.openai.title.en}</h3><p>{providers.openai.copy.en}</p>
</article><div class="effort-rail" role="tablist" aria-label="Reasoning effort">
<button data-effort="low" role="tab" aria-selected="false">LOW</button><button
class="active"
data-effort="medium"
role="tab"
aria-selected="true">MEDIUM</button
><button data-effort="high" role="tab" aria-selected="false">HIGH</button>
</div><article class="effort-detail" id="effort-detail" aria-live="polite">
<span>{efforts.medium.en[0]}</span><p>{efforts.medium.en[1]}</p><code
>{providers.openai.config}</code>
</article>
</div>
</section>
<section class="skills" id="skills">
<div>
<p class="eyebrow">Skills</p><h2>Write the right way<br /><em>once.</em></h2><p>
A skill is a reusable procedure. It can carry instructions, references, scripts, and
assets. It is not magical memory, and it does not replace acceptance criteria.
</p>
</div><div class="skill-explorer">
<SkillPackage
files={[
{ id: 'skill', path: 'SKILL.md', small: 'procedure and limits' },
{ id: 'references', path: 'references/', small: 'facts to consult' },
{ id: 'scripts', path: 'scripts/', small: 'repeatable checks' },
{ id: 'assets', path: 'assets/', small: 'templates and examples' },
]}
/><article class="skill-detail" id="skill-detail" aria-live="polite">
<span>{skillFiles.skill.icon}</span><div>
<strong>{skillFiles.skill.title}</strong><p>{skillFiles.skill.en}</p><small
>{labels.skillFileHint.en}</small>
</div>
</article>
</div>
</section>
<section class="skill-builder" id="create-skill">
<div class="section-label">
<span>Create a skill</span><span>repeatable pain reusable judgment</span>
</div><div class="builder-workbench">
<nav class="builder-steps" role="tablist" aria-label="Skill creation workflow">
{
Object.values(skillWorkflow).map((step) => (
<button
class:list={{ active: step.id === 'observe' }}
data-skill-step={step.id}
role="tab"
aria-selected={step.id === 'observe'}
>
<>
<b>{step.number}</b>
<span>{step.title.en}</span>
</>
</button>
))
}
</nav><article class="builder-detail" id="builder-detail" aria-live="polite">
<header>
<span>{skillWorkflow.observe.number}</span><small>{labels.workflow.question.en}</small>
</header><h3>{skillWorkflow.observe.title.en}</h3><blockquote>
{skillWorkflow.observe.question.en}
</blockquote><div class="builder-action">
<span>{labels.workflow.action.en}</span><p>{skillWorkflow.observe.action.en}</p>
</div><footer>
<div>
<span>{labels.workflow.artifact.en}</span><strong
>{skillWorkflow.observe.output.en}</strong>
</div><div>
<span>{labels.workflow.proof.en}</span><strong
>{skillWorkflow.observe.proof.en}</strong>
</div>
</footer>
</article>
</div>
</section>
<section class="skill-catalog" id="field-kit">
<div class="section-label">
<span>Common skills</span><span>choose behavior before model</span>
</div><div class="skill-deck">
<div class="skill-index" role="tablist" aria-label="Common agent skills">
{
Object.values(commonSkills).map((skill) => (
<button
class:list={{ active: skill.id === 'ponytail' }}
data-common-skill={skill.id}
role="tab"
aria-selected={skill.id === 'ponytail'}
>
<>
<span>{skill.kind.en}</span>
<strong>{skill.title}</strong>
<small>{skill.use.en}</small>
</>
</button>
))
}
</div><article class="common-skill-detail" id="common-skill-detail" aria-live="polite">
<header>
<span>{commonSkills.ponytail.number}</span><small
>{commonSkills.ponytail.kind.en}</small>
</header><h3>{commonSkills.ponytail.title}</h3><blockquote>
{commonSkills.ponytail.rule.en}
</blockquote><div class="common-skill-notes">
<div>
<span>{labels.commonSkill.whenToUse.en}</span><p>{commonSkills.ponytail.use.en}</p>
</div><div>
<span>{labels.commonSkill.example.en}</span><p>{commonSkills.ponytail.example.en}</p>
</div><div>
<span>{labels.commonSkill.watchOut.en}</span><p>{commonSkills.ponytail.caution.en}</p>
</div>
</div><a
class="skill-source"
href={commonSkills.ponytail.source}
target="_blank"
rel="noopener">{labels.commonSkill.source.en}</a>
</article>
</div><article class="install-skills">
<header>
<div>
<span>INSTALL PACK</span><strong
>Ask your coding agent to verify, install, and validate the skills.</strong>
</div><CopyPrompt target="prompt-install-skills" />
</header><pre><code id="prompt-install-skills">{install.en}</code></pre><footer>
Review every source before installation. Existing local skills must be preserved.
</footer>
</article>
</section>
<section class="hands-on" id="hands-on">
<div class="section-label">
<span>Hands-on</span><span>10 minutes / one missing feature</span>
</div><div class="hands-intro">
<div>
<p class="eyebrow">Tiny Tasks lab</p><h2>
Same task.<br />Better <em>operating system.</em>
</h2>
</div><div>
<p>
Start with a deliberately incomplete static task board. Run one prompt as written,
reset, then run the skill-enabled version.
</p><div class="starter-links">
<a href={`${base}hands-on/starter/`} class="starter-link">Open the starter </a><a
href={`${base}hands-on/rules/`}
class="starter-link">Open the rules lab </a>
</div>
</div>
</div><div class="prompt-compare">
<article class="prompt-card">
<header>
<div><span>RUN A</span><strong>Good prompt</strong></div><CopyPrompt
target="prompt-basic"
/>
</header><pre><code id="prompt-basic">{handsOn.en.basic}</code></pre><footer>
Clear context · constraints · acceptance · evidence
</footer>
</article><article class="prompt-card enhanced">
<header>
<div><span>RUN B</span><strong>Good prompt + skills</strong></div><CopyPrompt
target="prompt-skills"
/>
</header><pre><code id="prompt-skills">{handsOn.en.skills}</code></pre><footer>
Same contract · explicit working methods · stronger proof
</footer>
</article>
</div><p class="copy-status" id="copy-status" role="status" aria-live="polite"></p>
</section>
<aside class="rule">
<span>THE HUMAN JOB</span><strong
>The agent may be autonomous in execution. Intent, boundaries, and evidence remain yours.</strong>
</aside>
<section class="verification" id="verification">
<div class="section-label">
<span>Verification</span><span>run each gate separately</span>
</div><div class="verify-layers">
<article>
<span>01 · STATIC</span><h3>Lint and types</h3><p>
Format, lint, type-check. Fast and scoped to one file.
</p><code>pnpm lint; echo "lint=$?"</code>
</article><article>
<span>02 · BEHAVIOR</span><h3>Unit and contract</h3><p>
Tests that repeat. Run before claiming done.
</p><code>pnpm test; echo "test=$?"</code>
</article><article>
<span>03 · INTEGRATION</span><h3>Real UI and API</h3><p>
Drive the actual UI, API, or browser.
</p><code>pnpm check:ui; echo "ui=$?"</code>
</article>
</div>
</section>
<section class="sources">
<div class="section-label">
<span>Keep learning</span><span>12 new readings + primary docs</span>
</div><p>
Go deeper with official documentation, production case studies, Medium, and practitioner
workflows. <a href={`${base}rules/`}>Rules and enforcement case study </a>
<a href={`${base}skills-review/`}>Skills review desk </a>
<a href={`${base}docs/references/additional-reading.md`}>12-part reading path </a>
</p>
</section>
</main>
<GuideSelector rootSelector="#full-guide" data={selectorData} />
</BaseLayout>