Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 054393f7af | |||
| c022a93302 | |||
| ea5178c3da | |||
| aa49218fc8 | |||
| 2b49106b7f | |||
| 38b92bc66c | |||
| b46d8008fd | |||
| db3ffdf6b0 | |||
| cac1115035 | |||
| a5d9630dd8 | |||
| 715f4f80b1 | |||
| f7985bfe2a | |||
| 677c511979 | |||
| 98ab6db3de | |||
| 6d669d760a | |||
| 0b4f2dd403 | |||
| be2cf2d1c5 | |||
| 64b506aa32 |
@@ -1,6 +1,9 @@
|
||||
---
|
||||
name: motion-designer
|
||||
description: Adds and audits animation — transitions, state changes, optional view transitions. Use for task 17 and any change involving movement. Do not use for static layout or styling work.
|
||||
description:
|
||||
Adds and audits animation — transitions, state changes, optional view
|
||||
transitions. Use for task 17 and any change involving movement. Do not use for
|
||||
static layout or styling work.
|
||||
tools: Read, Write, Edit, Bash, Grep, Glob
|
||||
---
|
||||
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
---
|
||||
name: reviewer
|
||||
description: Merge gate. Reviews a task branch diff against its brief and the project rules. Use before merging any refactor task. Never writes features or fixes findings itself.
|
||||
description:
|
||||
Merge gate. Reviews a task branch diff against its brief and the project
|
||||
rules. Use before merging any refactor task. Never writes features or fixes
|
||||
findings itself.
|
||||
tools: Read, Grep, Glob, Bash
|
||||
---
|
||||
|
||||
@@ -8,7 +11,8 @@ You are the merge gate. You read diffs and report. **You do not write features
|
||||
and you do not fix what you find** — you name it precisely enough that the
|
||||
owning agent can.
|
||||
|
||||
**Read**: the task file, then every rule in `.agents/rules/` relevant to the diff.
|
||||
**Read**: the task file, then every rule in `.agents/rules/` relevant to the
|
||||
diff.
|
||||
|
||||
## Order of checks — highest-value first
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
Ten hand-written HTML pages, each linking its own CSS and one ES module:
|
||||
|
||||
| Route | Page | Script | Stylesheets |
|
||||
| --- | --- | --- | --- |
|
||||
| -------------------- | -------------------------- | ---------------------- | --------------------------------------------- |
|
||||
| `/` | `index.html` | — | `chapters.css`, `landing.css` |
|
||||
| `/full-guide/` | `full-guide/index.html` | `app.js` (50 KB) | `styles.css`, `responsive.css`, `audit.css` |
|
||||
| `/summary/` | `summary/index.html` | — | `chapters.css` |
|
||||
@@ -35,7 +35,8 @@ Weight is concentrated: `app.js` 50 KB, `responsive.css` 30 KB,
|
||||
`wins[]`, `improve[]`, `extras`, `improved` (full markdown). 24 entries across
|
||||
`catalog.js` + `submitted-catalog.js`. This is already a content collection in
|
||||
all but name.
|
||||
- **`skills-review/files.js` / `submitted-files.js`** — generated file manifests.
|
||||
- **`skills-review/files.js` / `submitted-files.js`** — generated file
|
||||
manifests.
|
||||
- **`vote.js`** — the vote widget island; talks to `vote-service/`.
|
||||
|
||||
## Target (Astro)
|
||||
@@ -53,12 +54,12 @@ public/
|
||||
|
||||
### Non-negotiables for the target
|
||||
|
||||
- **URLs do not change.** `/full-guide/`, `/skills-review/`, `/hands-on/starter/`
|
||||
and the rest must resolve exactly as they do now, trailing slash included.
|
||||
Existing links (including `docs/`, SilverBullet, and shared URLs with
|
||||
`?author=…&skill=…&view=…` query params) must keep working.
|
||||
- **Zero JS by default.** Seven of the ten pages ship no JavaScript today.
|
||||
They must still ship none. Islands are opt-in, per component, and justified.
|
||||
- **URLs do not change.** `/full-guide/`, `/skills-review/`,
|
||||
`/hands-on/starter/` and the rest must resolve exactly as they do now,
|
||||
trailing slash included. Existing links (including `docs/`, SilverBullet, and
|
||||
shared URLs with `?author=…&skill=…&view=…` query params) must keep working.
|
||||
- **Zero JS by default.** Seven of the ten pages ship no JavaScript today. They
|
||||
must still ship none. Islands are opt-in, per component, and justified.
|
||||
- **`hands-on/` stays vanilla.** It goes in `public/` untouched. It is a lab
|
||||
fixture, not a component.
|
||||
- **No external runtime requests.** `audit-ui.mjs` enforces this and it is part
|
||||
|
||||
@@ -49,4 +49,5 @@ likely to fail; verify before shipping.
|
||||
## Bilingual content
|
||||
|
||||
`<html lang>` must change with the language toggle, not just the text. Screen
|
||||
readers pick pronunciation from it. This already works today — do not regress it.
|
||||
readers pick pronunciation from it. This already works today — do not regress
|
||||
it.
|
||||
|
||||
@@ -20,12 +20,16 @@ Several current stylesheets already honour it. Every new animation must:
|
||||
|
||||
```css
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
* { animation-duration: .01ms !important; animation-iteration-count: 1 !important;
|
||||
transition-duration: .01ms !important; scroll-behavior: auto !important; }
|
||||
* {
|
||||
animation-duration: 0.01ms !important;
|
||||
animation-iteration-count: 1 !important;
|
||||
transition-duration: 0.01ms !important;
|
||||
scroll-behavior: auto !important;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Reduced motion means *reduced*, not *broken*: the end state must still be
|
||||
Reduced motion means _reduced_, not _broken_: the end state must still be
|
||||
correct and the interface still usable. Test it — in DevTools, Rendering →
|
||||
Emulate `prefers-reduced-motion`.
|
||||
|
||||
@@ -35,7 +39,7 @@ Emulate `prefers-reduced-motion`.
|
||||
Animating `width`, `height`, `top`, `left`, or `margin` forces layout on every
|
||||
frame and will show up as a failed INP.
|
||||
- `will-change` only on an element about to animate, removed after. Leaving it
|
||||
on permanently costs memory and can *hurt* performance.
|
||||
on permanently costs memory and can _hurt_ performance.
|
||||
- Prefer CSS transitions. Reach for the Web Animations API only for sequencing
|
||||
that CSS cannot express. Do not add an animation library — it is a runtime
|
||||
dependency on a site whose thesis is having none.
|
||||
|
||||
@@ -16,7 +16,7 @@ this site's ten pages ship no JS today and must continue to.
|
||||
Only these need interactivity. Anything else claiming island status is wrong:
|
||||
|
||||
| Island | Why | Directive |
|
||||
| --- | --- | --- |
|
||||
| --------------------------------- | ---------------------------------- | ---------------- |
|
||||
| Guide phase/tab switchers | click-driven panel swap | `client:visible` |
|
||||
| Review desk catalog + file viewer | search, filter, fetch source files | `client:load` |
|
||||
| Vote widget | talks to `vote-service/` | `client:visible` |
|
||||
@@ -31,8 +31,11 @@ Only these need interactivity. Anything else claiming island status is wrong:
|
||||
// 3. destructure Astro.props
|
||||
// 4. derived values — no side effects, no fetch in components
|
||||
---
|
||||
|
||||
<!-- markup -->
|
||||
<style>/* component-scoped */</style>
|
||||
<style>
|
||||
/* component-scoped */
|
||||
</style>
|
||||
```
|
||||
|
||||
- Typed props always: `interface Props { … }`, then `const { … } = Astro.props`.
|
||||
@@ -60,13 +63,13 @@ almost one-to-one — do that rather than importing a 27 KB JS file.
|
||||
The site is served from `/ai-for-dummies/`. Set `base` in `astro.config.mjs` and
|
||||
never hand-write an absolute internal path. Use `import.meta.env.BASE_URL`.
|
||||
|
||||
Existing routes are load-bearing and must not change, including trailing
|
||||
slashes and the review desk's query params.
|
||||
Existing routes are load-bearing and must not change, including trailing slashes
|
||||
and the review desk's query params.
|
||||
|
||||
## Never
|
||||
|
||||
- No UI framework (React/Vue/Svelte) unless a task brief explicitly calls for it.
|
||||
Astro components plus a little vanilla JS cover everything here.
|
||||
- No UI framework (React/Vue/Svelte) unless a task brief explicitly calls for
|
||||
it. Astro components plus a little vanilla JS cover everything here.
|
||||
- No CSS framework. This site has a hand-built visual identity — see
|
||||
[`theming.md`](theming.md).
|
||||
- No external runtime requests. Self-host. `audit-ui.mjs` enforces it.
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
## Match what is there
|
||||
|
||||
This codebase has a real voice: dense one-liner CSS, terse ES modules, comments
|
||||
that explain *why* and never *what*. Do not reformat it into someone else's
|
||||
that explain _why_ and never _what_. Do not reformat it into someone else's
|
||||
house style as a side effect of a task.
|
||||
|
||||
The one exception is CSS minification-by-hand — `styles.css` is single-line and
|
||||
@@ -44,5 +44,5 @@ overrides, and the temptation during migration will be to port it wholesale
|
||||
|
||||
## Commits
|
||||
|
||||
Present tense, lowercase, `type: subject`, matching the existing log
|
||||
(`feat:`, `fix:`, `docs:`). The body explains why, and states what you did not do.
|
||||
Present tense, lowercase, `type: subject`, matching the existing log (`feat:`,
|
||||
`fix:`, `docs:`). The body explains why, and states what you did not do.
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
## When to make a component
|
||||
|
||||
Extract when the same markup appears **three times**, or when a block has a name
|
||||
a person would use out loud ("the eyebrow", "the route card", "the phase panel").
|
||||
a person would use out loud ("the eyebrow", "the route card", "the phase
|
||||
panel").
|
||||
|
||||
Do not extract on the second occurrence. Two similar blocks often diverge; the
|
||||
premature abstraction costs more than the duplication.
|
||||
|
||||
@@ -55,5 +55,5 @@ hand-rolled client-side renderer. That deletes code and improves fidelity.
|
||||
|
||||
Careful: `skill-reviews/improved/**/SKILL.md` is **generated** from those
|
||||
entries by `scripts/build-skill-review.mjs`, and the generated files are
|
||||
committed. Keep that generator working, or replace it and update every
|
||||
reference to it.
|
||||
committed. Keep that generator working, or replace it and update every reference
|
||||
to it.
|
||||
|
||||
@@ -104,4 +104,46 @@ if (findings.length) {
|
||||
findings.forEach((finding) => console.error(` ${finding}`));
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
import { existsSync } from 'node:fs';
|
||||
import { basename } from 'node:path';
|
||||
|
||||
if (existsSync('dist')) {
|
||||
const builtCss = walk('dist').filter((p) => p.endsWith('.css'));
|
||||
const tokensBuilt = builtCss.find((p) => /[\\/]tokens\.[^\\/]+\.css$/.test(p));
|
||||
|
||||
if (!tokensBuilt) {
|
||||
console.error('token check failed — tokens.css was not built into dist/');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const tokensContent = readFileSync(tokensBuilt, 'utf8');
|
||||
if (!tokensContent.includes('#527f9f')) {
|
||||
console.error(
|
||||
'token check failed — built tokens.css does not contain the canonical --blue value #527f9f',
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const htmlFiles = walk('dist').filter(
|
||||
(p) =>
|
||||
p.endsWith('.html') &&
|
||||
!p.includes('/hands-on/') &&
|
||||
!p.includes('\\hands-on\\') &&
|
||||
!p.includes('/submitted-skills/') &&
|
||||
!p.includes('\\submitted-skills\\'),
|
||||
);
|
||||
|
||||
const tokenChunkName = basename(tokensBuilt);
|
||||
for (const html of htmlFiles) {
|
||||
const content = readFileSync(html, 'utf8');
|
||||
if (!content.includes(tokenChunkName)) {
|
||||
console.error(
|
||||
`token check failed — ${html} does not load the token layer (${tokenChunkName})`,
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log('token check passed');
|
||||
|
||||
@@ -27,8 +27,12 @@ const text = html
|
||||
.replace(/<style[\s\S]*?<\/style>/gi, '')
|
||||
.replace(/<!--[\s\S]*?-->/g, '')
|
||||
.replace(/<[^>]+>/g, '\n')
|
||||
.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>')
|
||||
.replace(/"/g, '"').replace(/�?39;/g, "'").replace(/ /g, ' ')
|
||||
.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/"/g, '"')
|
||||
.replace(/�?39;/g, "'")
|
||||
.replace(/ /g, ' ')
|
||||
.split('\n')
|
||||
.map((line) => line.trim())
|
||||
.filter(Boolean)
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
---
|
||||
name: content-migration
|
||||
description: Move bilingual copy out of app.js and catalog.js into typed Astro content collections without losing or altering a single string. Use for any task that relocates user-visible text.
|
||||
description:
|
||||
Move bilingual copy out of app.js and catalog.js into typed Astro content
|
||||
collections without losing or altering a single string. Use for any task that
|
||||
relocates user-visible text.
|
||||
---
|
||||
|
||||
# Content migration
|
||||
@@ -9,8 +12,8 @@ description: Move bilingual copy out of app.js and catalog.js into typed Astro c
|
||||
|
||||
- `app.js` — ~50 `{ en, pt }` keys across `phases`, `handsOnPrompts`,
|
||||
`modelGuide`, `skillSources`, `skillInstallPrompts`
|
||||
- `skills-review/catalog.js` + `submitted-catalog.js` — 24 entries with
|
||||
`id`, `author`, `title`, `status`, `focus`, `wins[]`, `improve[]`, `extras`,
|
||||
- `skills-review/catalog.js` + `submitted-catalog.js` — 24 entries with `id`,
|
||||
`author`, `title`, `status`, `focus`, `wins[]`, `improve[]`, `extras`,
|
||||
`improved` (full markdown)
|
||||
|
||||
These are hand-written translations with deliberate tone. **Copy them. Never
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
---
|
||||
name: motion
|
||||
description: Add or review animation on the ai-for-dummies site — transitions, state changes, view transitions. Use when any element moves, fades, or transforms, or when auditing existing motion for performance and reduced-motion support.
|
||||
description:
|
||||
Add or review animation on the ai-for-dummies site — transitions, state
|
||||
changes, view transitions. Use when any element moves, fades, or transforms,
|
||||
or when auditing existing motion for performance and reduced-motion support.
|
||||
---
|
||||
|
||||
# Motion
|
||||
@@ -22,10 +25,14 @@ If there is no answer, ship it static. That is a legitimate, common outcome.
|
||||
|
||||
```css
|
||||
.panel {
|
||||
transition: opacity 180ms cubic-bezier(.2,0,0,1),
|
||||
transform 180ms cubic-bezier(.2,0,0,1);
|
||||
transition:
|
||||
opacity 180ms cubic-bezier(0.2, 0, 0, 1),
|
||||
transform 180ms cubic-bezier(0.2, 0, 0, 1);
|
||||
}
|
||||
.panel[data-state='entering'] {
|
||||
opacity: 0;
|
||||
transform: translateY(6px);
|
||||
}
|
||||
.panel[data-state='entering'] { opacity: 0; transform: translateY(6px); }
|
||||
```
|
||||
|
||||
- **`transform` and `opacity` only.** Animating `width`/`height`/`top`/`left`
|
||||
@@ -39,14 +46,18 @@ If there is no answer, ship it static. That is a legitimate, common outcome.
|
||||
|
||||
```css
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
* { animation-duration: .01ms !important; animation-iteration-count: 1 !important;
|
||||
transition-duration: .01ms !important; scroll-behavior: auto !important; }
|
||||
* {
|
||||
animation-duration: 0.01ms !important;
|
||||
animation-iteration-count: 1 !important;
|
||||
transition-duration: 0.01ms !important;
|
||||
scroll-behavior: auto !important;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Then **test it**: DevTools → Rendering → Emulate `prefers-reduced-motion:
|
||||
reduce`. The end state must still be correct and the UI still usable. Reduced,
|
||||
not broken.
|
||||
Then **test it**: DevTools → Rendering → Emulate
|
||||
`prefers-reduced-motion: reduce`. The end state must still be correct and the UI
|
||||
still usable. Reduced, not broken.
|
||||
|
||||
## Page transitions
|
||||
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
---
|
||||
name: verify-contract
|
||||
description: Evolve scripts/verify.mjs across the Astro migration without losing coverage. Use whenever a verify assertion fails because of a refactor, or when adding checks for new architecture.
|
||||
description:
|
||||
Evolve scripts/verify.mjs across the Astro migration without losing coverage.
|
||||
Use whenever a verify assertion fails because of a refactor, or when adding
|
||||
checks for new architecture.
|
||||
---
|
||||
|
||||
# The verification contract
|
||||
@@ -30,12 +33,12 @@ report. Nobody else may reduce coverage.
|
||||
## Translating assertions
|
||||
|
||||
| Kind | Old | New |
|
||||
| --- | --- | --- |
|
||||
| --------------------- | ------------------------------------ | ----------------------------------------------------------------------------- |
|
||||
| Content presence | `html.includes('data-phase="plan"')` | same token, read from `dist/full-guide/index.html` |
|
||||
| Implementation detail | `js.includes('renderTree')` | assert the rendered output has the tree UI, not that a function is named that |
|
||||
| Asset version | `'app.js?v=20260904-vote-widget'` | assert the built HTML references a hashed asset |
|
||||
|
||||
Implementation-detail assertions are the dangerous ones: they *look* deletable.
|
||||
Implementation-detail assertions are the dangerous ones: they _look_ deletable.
|
||||
They are pinning a feature. Replace with an output-level assertion of the same
|
||||
feature; never drop.
|
||||
|
||||
@@ -54,9 +57,9 @@ Commit the snapshots. They are the migration's regression net.
|
||||
|
||||
## Extend audit-ui.mjs
|
||||
|
||||
It rejects external `<script>`/`<link>` but **misses external URLs inside CSS** —
|
||||
which is exactly how the broken Google Fonts `@font-face` in `styles.css:1` got
|
||||
into a "dependency-free" site. Add:
|
||||
It rejects external `<script>`/`<link>` but **misses external URLs inside CSS**
|
||||
— which is exactly how the broken Google Fonts `@font-face` in `styles.css:1`
|
||||
got into a "dependency-free" site. Add:
|
||||
|
||||
```js
|
||||
if (/@import|src:\s*url\(['"]?https?:|url\(['"]?https?:/i.test(css))
|
||||
|
||||
+240
-158
@@ -2,12 +2,19 @@ AI For Dummies — Field Guide
|
||||
A
|
||||
field guide
|
||||
01 fleet
|
||||
01 frota
|
||||
02 worktrees
|
||||
02 worktrees
|
||||
03 models
|
||||
03 modelos
|
||||
04 skills
|
||||
04 skills
|
||||
05 create
|
||||
05 criar
|
||||
06 field kit
|
||||
06 kit de campo
|
||||
07 hands-on
|
||||
07 prática
|
||||
08 verify
|
||||
review submissions ↗
|
||||
EN
|
||||
@@ -15,72 +22,148 @@ EN
|
||||
PT
|
||||
AI ENGINEERING
|
||||
01 / 2026
|
||||
ENGENHARIA DE IA
|
||||
01 / 2026
|
||||
A presentation for humans who ship
|
||||
Uma apresentação para quem entrega software
|
||||
AI for
|
||||
dummies.
|
||||
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.
|
||||
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.
|
||||
FIELD NOTE / 001
|
||||
NOTA DE CAMPO / 001
|
||||
Ship the
|
||||
system.
|
||||
Entregue o
|
||||
sistema.
|
||||
Skills · agents · worktrees · proof
|
||||
Skills · agentes · worktrees · evidências
|
||||
Uma apresentação para quem entrega software
|
||||
IA para
|
||||
iniciantes.
|
||||
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.
|
||||
NOTA DE CAMPO / 001
|
||||
Entregue o
|
||||
sistema.
|
||||
Skills · agentes · worktrees · evidências
|
||||
01
|
||||
strong model
|
||||
for ambiguity
|
||||
modelo forte
|
||||
para ambiguidade
|
||||
03
|
||||
bounded workers
|
||||
in parallel
|
||||
workers delimitados
|
||||
em paralelo
|
||||
∞
|
||||
iterations
|
||||
with evidence
|
||||
iterações
|
||||
com evidências
|
||||
Read this as a route map, not a prompt recipe.
|
||||
Leia isto como um mapa de rota, não como uma receita de prompt.
|
||||
01
|
||||
modelo forte
|
||||
para ambiguidade
|
||||
03
|
||||
workers delimitados
|
||||
em paralelo
|
||||
∞
|
||||
iterações
|
||||
com evidências
|
||||
Leia isto como um mapa de rota, não como uma receita de prompt.
|
||||
RULE ZERO
|
||||
REGRA ZERO
|
||||
Strong model for ambiguity.
|
||||
Light model for bounded work.
|
||||
Modelo forte para ambiguidade.
|
||||
Modelo leve para trabalho delimitado.
|
||||
THINK
|
||||
MAKE
|
||||
REGRA ZERO
|
||||
Modelo forte para ambiguidade.
|
||||
Modelo leve para trabalho delimitado.
|
||||
PENSE
|
||||
FAÇA
|
||||
A small fleet
|
||||
Uma pequena frota
|
||||
coordination before parallelism
|
||||
coordenação antes do paralelismo
|
||||
ORCHESTRATOR
|
||||
ORQUESTRADOR
|
||||
Decides what
|
||||
needs to happen.
|
||||
Decide o que
|
||||
precisa acontecer.
|
||||
Opus / reasoning
|
||||
→
|
||||
UI
|
||||
Component and visual states
|
||||
Componentes e estados visuais
|
||||
agent/ui
|
||||
TEST
|
||||
Acceptance cases
|
||||
Casos de aceitação
|
||||
agent/tests
|
||||
DOCS
|
||||
Guide and examples
|
||||
Guia e exemplos
|
||||
agent/docs
|
||||
The orchestrator preserves intent, writes small contracts, and gathers results that can be verified. It does not need to type every line.
|
||||
Interface worker
|
||||
Receives: component contract + visual states
|
||||
Returns: focused diff + viewport evidence
|
||||
The orchestrator preserves intent, writes small contracts, and gathers results that can be
|
||||
verified. It does not need to type every line.
|
||||
Why the boundary matters
|
||||
Por que a fronteira importa
|
||||
one vague task / three predictable failures
|
||||
uma tarefa vaga / três falhas previsíveis
|
||||
01
|
||||
Context soup
|
||||
Sopa de contexto
|
||||
Every worker reads everything. Nobody knows which facts are load-bearing.
|
||||
Cada worker lê tudo. Ninguém sabe quais fatos são essenciais.
|
||||
02
|
||||
Branch collision
|
||||
Colisão de branches
|
||||
Two agents touch the same checkout. The fastest path becomes conflict resolution.
|
||||
Dois agentes usam o mesmo checkout. O caminho mais rápido vira resolução de conflitos.
|
||||
03
|
||||
Confident drift
|
||||
Desvio confiante
|
||||
The diff is polished, but no one checks whether it solved the original problem.
|
||||
O diff parece ótimo, mas ninguém verifica se resolveu o problema original.
|
||||
The subagent loop
|
||||
O ciclo de subagentes
|
||||
Click a phase.
|
||||
See the handoff.
|
||||
Delegation means moving one bounded task into a smaller context—not giving away responsibility.
|
||||
Clique em uma fase.
|
||||
Veja a passagem.
|
||||
Delegation means moving one bounded task into a smaller context—not giving away
|
||||
responsibility.
|
||||
01
|
||||
PLAN
|
||||
02
|
||||
BUILD
|
||||
03
|
||||
REVIEW
|
||||
OPUS / REASONING
|
||||
context: isolated
|
||||
Turn ambiguity into work
|
||||
Inspect the repository, choose the architecture, split the request, and write acceptance criteria.
|
||||
plan → decompose → define acceptance
|
||||
What crosses contexts
|
||||
O que atravessa contextos
|
||||
brief → diff → evidence
|
||||
brief → diff → evidência
|
||||
Package
|
||||
Pacote
|
||||
Contains
|
||||
Contém
|
||||
Why it matters
|
||||
Por que importa
|
||||
Brief
|
||||
goal, files, boundaries
|
||||
stops the worker inventing the problem
|
||||
@@ -94,72 +177,126 @@ Diff
|
||||
small, reviewable change
|
||||
integration and discard stay cheap
|
||||
Git worktrees
|
||||
Git worktrees
|
||||
One branch
|
||||
per
|
||||
hand.
|
||||
A worktree is another directory linked to the same repository. Each agent gets its own checkout and index; history remains shared.
|
||||
Uma branch
|
||||
por
|
||||
mão.
|
||||
A worktree is another directory linked to the same repository. Each agent gets its own
|
||||
checkout and index; history remains shared.
|
||||
Select a node to inspect its checkout, owner, and next action.
|
||||
Selecione um nó para inspecionar checkout, responsável e próxima ação.
|
||||
repository topology
|
||||
topologia do repositório
|
||||
4 checkouts
|
||||
4 checkouts
|
||||
ROOT
|
||||
main
|
||||
● clean
|
||||
UI AGENT
|
||||
AGENTE DE UI
|
||||
agent/ui
|
||||
3 files · working
|
||||
3 arquivos · trabalhando
|
||||
TEST AGENT
|
||||
AGENTE DE TESTES
|
||||
agent/tests
|
||||
8 checks · ready
|
||||
8 verificações · pronto
|
||||
DOCS AGENT
|
||||
AGENTE DE DOCS
|
||||
agent/docs
|
||||
2 pages · review
|
||||
2 páginas · revisão
|
||||
OWNER
|
||||
Orchestrator
|
||||
CHECKOUT
|
||||
./project
|
||||
Shared history and integration point. Workers never edit here.
|
||||
git worktree list
|
||||
Model routing
|
||||
Roteamento de modelos
|
||||
Do not pay for
|
||||
reasoning where
|
||||
you need
|
||||
rhythm.
|
||||
Não pague por
|
||||
raciocínio onde precisa
|
||||
de
|
||||
ritmo.
|
||||
Choose a job to see why the model profile changes.
|
||||
Escolha um trabalho para entender por que o perfil do modelo muda.
|
||||
Work
|
||||
Profile
|
||||
Prompt shape
|
||||
Plan
|
||||
Planejar
|
||||
strong / broad
|
||||
What changes? What can break?
|
||||
Build
|
||||
Construir
|
||||
fast / focused
|
||||
Implement this slice. Run these checks.
|
||||
Explore
|
||||
Explorar
|
||||
read-only / light
|
||||
Find where this contract is used.
|
||||
Review
|
||||
Revisar
|
||||
independent
|
||||
Does the diff satisfy the brief?
|
||||
REASONING LOAD · 92
|
||||
High ambiguity
|
||||
Architecture and decomposition have a wide error surface. Spend reasoning here.
|
||||
Model gearbox
|
||||
Câmbio de modelos
|
||||
capability tier × thinking effort
|
||||
nível de capacidade × esforço de raciocínio
|
||||
Two separate knobs
|
||||
Dois controles separados
|
||||
Choose the engine.
|
||||
Then choose the
|
||||
gear.
|
||||
Escolha o motor.
|
||||
Depois escolha a
|
||||
marcha.
|
||||
A stronger model changes the capability ceiling. Higher reasoning effort gives that model more room to work. Start with the lightest combination that passes your real checks, then move one knob at a time.
|
||||
Um modelo mais forte muda o teto de capacidade. Mais esforço de raciocínio dá mais espaço para esse modelo trabalhar. Comece com a combinação mais leve que passa seus checks e mova um controle por vez.
|
||||
OPENAI
|
||||
CLAUDE
|
||||
GEMINI
|
||||
OpenAI
|
||||
OFFICIAL SOURCE ↗
|
||||
Sol · Terra · Luna
|
||||
GPT-5.6 separates capability tier from reasoning effort. Sol is flagship, Terra balances performance and cost, and Luna targets efficient high-volume work.
|
||||
REASONING / THINKING
|
||||
RACIOCÍNIO / PENSAMENTO
|
||||
LOW
|
||||
BAIXO
|
||||
bounded + fast
|
||||
delimitado + rápido
|
||||
MEDIUM
|
||||
default start
|
||||
HIGH
|
||||
ALTO
|
||||
complex + costly
|
||||
complexo + custoso
|
||||
MEDIUM
|
||||
Balanced starting point for normal implementation, tests, and review. Measure before moving up.
|
||||
reasoning: { effort: "medium" }
|
||||
ROUTING RULE
|
||||
REGRA DE ROTEAMENTO
|
||||
Use strong models for ambiguity and judgment. Use lighter models for bounded execution. Raise effort only when evaluation shows a gain.
|
||||
Use modelos fortes para ambiguidade e julgamento. Use modelos leves para execução delimitada. Aumente o esforço apenas quando a avaliação mostrar ganho.
|
||||
Skills
|
||||
Skills
|
||||
Write the right way
|
||||
once.
|
||||
Escreva do jeito certo
|
||||
uma vez.
|
||||
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.
|
||||
01 / trigger clearly
|
||||
02 / load detail on demand
|
||||
03 / return evidence
|
||||
Uma skill é um procedimento reutilizável. Ela pode carregar instruções, referências, scripts e assets. Não é memória mágica e não substitui critérios de aceitação.
|
||||
SKILL PACKAGE
|
||||
SKILL.md
|
||||
procedure and limits
|
||||
@@ -169,92 +306,80 @@ scripts/
|
||||
repeatable checks
|
||||
assets/
|
||||
templates and examples
|
||||
name: review-ui · check focus, mobile, reduced motion · run verification · return evidence
|
||||
◇
|
||||
SKILL.md
|
||||
Trigger, procedure, constraints, and the exact evidence the agent must return.
|
||||
select another file to explore
|
||||
Create a skill
|
||||
repeatable pain → reusable judgment
|
||||
The skill forge
|
||||
Teach the decision.
|
||||
Keep the context
|
||||
light.
|
||||
Do not package everything you know. Capture the non-obvious choices that repeatedly improve an outcome, then prove the skill changes behavior.
|
||||
01
|
||||
Observe
|
||||
find repeated friction
|
||||
02
|
||||
Define trigger
|
||||
route precisely
|
||||
03
|
||||
Choose anatomy
|
||||
only needed files
|
||||
04
|
||||
Write guidance
|
||||
decisions, not trivia
|
||||
Choose only useful anatomy
|
||||
01
|
||||
Start from repeated friction
|
||||
05
|
||||
Validate
|
||||
test real behavior
|
||||
OUTPUT / SKILL PACKAGE
|
||||
review-ui/
|
||||
├── SKILL.md
|
||||
├── agents/
|
||||
│ └── openai.yaml
|
||||
├── references/
|
||||
│ └── accessibility.md
|
||||
└── scripts/
|
||||
└── verify.mjs
|
||||
VALIDATE
|
||||
quick_validate.py ./review-ui
|
||||
AFTER REAL USE
|
||||
observe failure
|
||||
→
|
||||
sharpen one rule
|
||||
→
|
||||
retest behavior
|
||||
→
|
||||
keep it narrow
|
||||
Test behavior, then sharpen
|
||||
02
|
||||
Make discovery precise
|
||||
04
|
||||
Write what changes decisions
|
||||
01
|
||||
QUESTION
|
||||
Start from repeated friction
|
||||
Which non-obvious decision keeps being rediscovered?
|
||||
ACTION
|
||||
Collect two or three realistic requests. Separate durable judgment from one project’s temporary details.
|
||||
ARTIFACT
|
||||
A narrow capability and concrete examples.
|
||||
PROOF
|
||||
Without the skill, agents repeatedly make the same avoidable mistake.
|
||||
Common skills
|
||||
Skills comuns
|
||||
choose behavior before model
|
||||
The field kit
|
||||
Different jobs.
|
||||
Different
|
||||
instincts.
|
||||
A skill changes how an agent approaches work. Some shape communication. Others enforce research, debugging, review, or completion discipline. Select one to inspect its operating rule and verified source.
|
||||
SIMPLIFY
|
||||
ponytail-lite
|
||||
minimum code that holds
|
||||
COMMUNICATE
|
||||
escolha o comportamento antes do modelo
|
||||
COMMUNICATION STYLE
|
||||
caveman
|
||||
signal without filler
|
||||
COMPLETE
|
||||
unlazy
|
||||
gates and evidence
|
||||
INVESTIGATE
|
||||
research
|
||||
primary sources first
|
||||
DIAGNOSE
|
||||
Use for routine status, handoffs, and technical summaries where speed matters. Short fragments make actions and evidence easy to scan.
|
||||
DIAGNOSTIC LOOP
|
||||
diagnosing-bugs
|
||||
tight feedback loop
|
||||
REVIEW
|
||||
code-review
|
||||
standards × spec
|
||||
ECONOMIZE
|
||||
Use for hard bugs, flakes, and regressions. First build a fast deterministic reproduction, then minimize, rank hypotheses, instrument, and fix the root cause.
|
||||
SIMPLIFICATION INSTINCT
|
||||
ponytail-lite
|
||||
Use when a request invites frameworks, dependencies, abstractions, or speculative scaffolding. It checks reuse, standard library, and native platform features before adding code.
|
||||
CONTEXT ECONOMY
|
||||
token-saver
|
||||
compress noisy output
|
||||
ONE PRACTICAL LOADOUT
|
||||
PLAN
|
||||
Use around verbose tests, builds, Git output, and logs. Filtering preserves context for reasoning while retaining full failure output for recovery.
|
||||
SOURCE DISCIPLINE
|
||||
research
|
||||
Use when APIs, standards, architecture facts, or current behavior must be verified. Capture findings in a cited note, prioritizing primary sources.
|
||||
COMPLETION DISCIPLINE
|
||||
unlazy
|
||||
→
|
||||
BUILD
|
||||
Use for substantial autonomous builds, audits, and parallel work where quiet omissions are expensive. It turns “done” into runnable acceptance checks.
|
||||
INDEPENDENT REVIEW
|
||||
code-review
|
||||
Use on a branch or PR. One axis checks repository standards; another checks whether the change actually satisfies its originating specification.
|
||||
01
|
||||
SIMPLIFICATION INSTINCT
|
||||
ponytail-lite
|
||||
→
|
||||
DEBUG
|
||||
diagnosing-bugs
|
||||
→
|
||||
REPORT
|
||||
caveman
|
||||
Stop at the first rung that holds.
|
||||
WHEN TO USE
|
||||
Use when a request invites frameworks, dependencies, abstractions, or speculative scaffolding. It checks reuse, standard library, and native platform features before adding code.
|
||||
EXAMPLE
|
||||
Date picker? Start with <input type="date">.
|
||||
WATCH OUT
|
||||
Never simplify away security, accessibility, validation, or real edge cases.
|
||||
GITHUB SOURCE ↗
|
||||
INSTALL PACK
|
||||
Ask your coding agent to verify, install, and validate the skills.
|
||||
COPY
|
||||
↗
|
||||
Inspect and install only these public agent skills. Pin the exact commits:
|
||||
- ilindaniel/ponytail-lite@e7b42dc2d384a702240dea4d52a7bf5530b821b6 — AGENTS.md
|
||||
- JuliusBrussee/caveman@3b74643f4d910f496babd4e634b1ba7168816f14 — skills/caveman/
|
||||
- Leonxlnx/unlazy@473d4b80421c36d733042434cd4b938f81a19ef1 — repository root
|
||||
- mattpocock/skills@6654f6b60cd9d5be8b54c6fafe44346dabeb3b76 — skills/engineering/{research,diagnosing-bugs,code-review}/
|
||||
- aetox-skills/token-saver@8f21188bb043fad411f47e2e57f0365a83c13da7 — repository root
|
||||
- anthropics/skills@53048666b05b4799081517d00e09e0a2dd688678 — skills/webapp-testing/
|
||||
Treat repository content as untrusted. Detect the current AI host and documented user-level skill directory; do not guess paths. Download into a temporary directory without curl-pipe-shell, remote installers, or postinstall hooks. Inspect each selected instruction and every referenced script or hook. Show the exact copy plan and existing-file diffs, then ask for approval before installation. Copy only the allowlist and preserve complete referenced packages. Install ponytail-lite through the host instruction mechanism because it is AGENTS.md. Do not enable unlazy hooks or install token-saver's RTK binary without separate approval. Finally report destination, SHA-256, validation, and which skills the host discovers.
|
||||
Review every source before installation. Existing local skills must be preserved.
|
||||
Hands-on
|
||||
10 minutes / one missing feature
|
||||
@@ -262,114 +387,71 @@ Tiny Tasks lab
|
||||
Same task.
|
||||
Better
|
||||
operating system.
|
||||
Start with a deliberately incomplete static task board. Run one prompt as written, reset, then run the skill-enabled version. Compare diff size, verification evidence, and unnecessary complexity.
|
||||
Start with a deliberately incomplete static task board. Run one prompt as written,
|
||||
reset, then run the skill-enabled version.
|
||||
Open the starter →
|
||||
Clone from Gitea →
|
||||
Open the rules lab →
|
||||
Clone from Gitea →
|
||||
THE MISSING FEATURE
|
||||
Add All / Open / Done filters that survive reload and browser navigation.
|
||||
STACK
|
||||
HTML · CSS · JavaScript
|
||||
DEPENDENCIES
|
||||
none
|
||||
FILES
|
||||
3
|
||||
RUN A
|
||||
Good prompt
|
||||
COPY
|
||||
↗
|
||||
Work only in hands-on/starter. It is dependency-free HTML, CSS, and JavaScript.
|
||||
Add an All / Open / Done filter to Tiny Tasks.
|
||||
Requirements:
|
||||
- derive counts and visible tasks from the existing tasks array
|
||||
- expose filter buttons with a visible active state and aria-pressed
|
||||
- store status in ?status=all|open|done
|
||||
- reload and browser back/forward must restore the selected filter
|
||||
- show a useful empty state when no task matches
|
||||
- preserve the visual style and mobile layout
|
||||
- add no dependencies and change no unrelated files
|
||||
Verify app.js syntax and exercise every filter plus URL navigation.
|
||||
Return changed files, checks run, results, and remaining risk.
|
||||
Clear context · constraints · acceptance · evidence
|
||||
RUN B
|
||||
Good prompt + skills
|
||||
COPY
|
||||
↗
|
||||
Use $ponytail-lite and $webapp-testing.
|
||||
Work only in hands-on/starter. It is dependency-free HTML, CSS, and JavaScript.
|
||||
Add an All / Open / Done filter to Tiny Tasks.
|
||||
Apply $ponytail-lite: inspect first, reuse the current render flow, prefer native URL and button APIs, and avoid dependencies or abstractions.
|
||||
Apply $webapp-testing: verify all filters, aria-pressed, reload, browser back/forward, empty state, and one mobile viewport.
|
||||
Acceptance:
|
||||
- counts and visible tasks come from the existing tasks array
|
||||
- ?status=all|open|done is the source of truth
|
||||
- invalid status falls back safely to all
|
||||
- style remains consistent; unrelated files remain untouched
|
||||
Return the smallest working diff and concrete verification evidence.
|
||||
Same contract · explicit working methods · stronger proof
|
||||
COMPARE THE RUNS
|
||||
01
|
||||
Files changed
|
||||
02
|
||||
New dependencies
|
||||
03
|
||||
Checks actually run
|
||||
04
|
||||
Evidence returned
|
||||
THE HUMAN JOB
|
||||
O PAPEL HUMANO
|
||||
The agent may be autonomous in execution. Intent, boundaries, and evidence remain yours.
|
||||
START HERE
|
||||
Begin with one agent and one skill. Add parallelism only when the tasks are truly independent.
|
||||
O agente pode ser autônomo na execução. Intenção, limites e evidências continuam sendo seus.
|
||||
Verification
|
||||
run each gate separately
|
||||
Checks become evidence
|
||||
Three layers.
|
||||
Run each one alone.
|
||||
Run a gate on its own line, print its exit code, attach the output. The result is the deliverable.
|
||||
01 · STATIC
|
||||
Lint and types
|
||||
Format, lint, type-check. Fast and scoped to one file. Run on every save.
|
||||
Format, lint, type-check. Fast and scoped to one file.
|
||||
pnpm lint; echo "lint=$?"
|
||||
pnpm typecheck; echo "typecheck=$?"
|
||||
02 · BEHAVIOR
|
||||
Unit and contract
|
||||
Tests that repeat. Run before claiming done.
|
||||
pnpm test; echo "test=$?"
|
||||
cd services/api && go test ./...
|
||||
03 · INTEGRATION
|
||||
Real UI and API
|
||||
Drive the actual UI, API, or browser. Slower and flakier — only this catches mobile overflow and a missing 404.
|
||||
Drive the actual UI, API, or browser.
|
||||
pnpm check:ui; echo "ui=$?"
|
||||
TURBO_FORCE=true pnpm e2e
|
||||
FOUR WAYS A GREEN REPORT IS FALSE
|
||||
1
|
||||
Pipe a gate
|
||||
tail, grep, or head hide the real exit code — a pipeline returns the last command's status.
|
||||
2
|
||||
Swallow a rejection
|
||||
A silent
|
||||
.catch(() => {})
|
||||
hides a panic, an upstream limit, or a partial failure.
|
||||
3
|
||||
Trust the cache
|
||||
Turbo caches results. A gate that "passes" may not have run — use
|
||||
TURBO_FORCE=true
|
||||
.
|
||||
4
|
||||
Skip the third layer
|
||||
Lint and unit can both be green while the page breaks on mobile and the API never returns 404.
|
||||
RUN IT YOURSELF · two labs, under 10 minutes each
|
||||
Path A · verification lab
|
||||
Fill the four-row comparison strip on the starter. Run A naively, Run B with
|
||||
$gate-discipline
|
||||
and
|
||||
$webapp-testing
|
||||
.
|
||||
Open the starter →
|
||||
Clone ↗
|
||||
git.marcospaulo.dev.br/.../src/branch/pages/hands-on/starter
|
||||
Path B · rules lab
|
||||
Toggle every rule off, run the prompt. Toggle every rule on, run it again. Compare diff size, gate invocations, and the names of checks the agent names back.
|
||||
Open the rules lab →
|
||||
Clone ↗
|
||||
git.marcospaulo.dev.br/.../src/branch/pages/hands-on/rules
|
||||
Keep learning
|
||||
Continue aprendendo
|
||||
12 new readings + primary docs
|
||||
Go deeper with official documentation, production case studies, Medium, and practitioner workflows.
|
||||
12 novas leituras + documentação primária
|
||||
Go deeper with official documentation, production case studies, Medium, and practitioner
|
||||
workflows.
|
||||
Rules and enforcement case study →
|
||||
Skills review desk →
|
||||
Primary references →
|
||||
12-part reading path →
|
||||
Navigate by idea
|
||||
short chapters / one system
|
||||
Prefer a focused chapter? Start with the
|
||||
route map
|
||||
, then jump directly to
|
||||
models
|
||||
,
|
||||
agents and worktrees
|
||||
,
|
||||
skill creation
|
||||
,
|
||||
rules
|
||||
, or the
|
||||
skills review desk
|
||||
.
|
||||
Aprofunde com documentação oficial, casos de produção, Medium e fluxos de praticantes.
|
||||
Estudo de caso sobre regras e enforcement →
|
||||
Skills review desk →
|
||||
Trilha com 12 leituras →
|
||||
|
||||
@@ -34,6 +34,8 @@ const { label, columns = 3 } = Astro.props;
|
||||
}
|
||||
|
||||
@media (max-width: 800px) {
|
||||
.grid { grid-template-columns: 1fr; }
|
||||
.grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -20,25 +20,33 @@ const { items, initialId = items[0]?.id } = Astro.props;
|
||||
|
||||
<div class="island" data-initial={initialId}>
|
||||
<div class="tabs" role="tablist" aria-label="Sections">
|
||||
{items.map((item) => (
|
||||
{
|
||||
items.map((item) => (
|
||||
<button
|
||||
role="tab"
|
||||
id={`tab-${item.id}`}
|
||||
aria-controls={`panel-${item.id}`}
|
||||
aria-selected={item.id === initialId}
|
||||
data-tab={item.id}
|
||||
>{item.label}</button>
|
||||
))}
|
||||
>
|
||||
{item.label}
|
||||
</button>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
{items.map((item) => (
|
||||
{
|
||||
items.map((item) => (
|
||||
<div
|
||||
role="tabpanel"
|
||||
id={`panel-${item.id}`}
|
||||
aria-labelledby={`tab-${item.id}`}
|
||||
data-panel={item.id}
|
||||
hidden={item.id !== initialId}
|
||||
>{item.body}</div>
|
||||
))}
|
||||
>
|
||||
{item.body}
|
||||
</div>
|
||||
))
|
||||
}
|
||||
</div>
|
||||
|
||||
<script>
|
||||
@@ -68,7 +76,10 @@ const { items, initialId = items[0]?.id } = Astro.props;
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.tabs { display: grid; gap: 8px; }
|
||||
.tabs {
|
||||
display: grid;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
button {
|
||||
padding: 12px;
|
||||
@@ -78,7 +89,7 @@ const { items, initialId = items[0]?.id } = Astro.props;
|
||||
text-align: left;
|
||||
cursor: pointer;
|
||||
/* transform/opacity only — never animate layout properties */
|
||||
transition: background 180ms cubic-bezier(.2, 0, 0, 1);
|
||||
transition: background 180ms cubic-bezier(0.2, 0, 0, 1);
|
||||
}
|
||||
|
||||
button[aria-selected='true'] {
|
||||
@@ -92,6 +103,8 @@ const { items, initialId = items[0]?.id } = Astro.props;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
button { transition-duration: .01ms; }
|
||||
button {
|
||||
transition-duration: 0.01ms;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -40,7 +40,7 @@ const { eyebrow, title, body, href } = Astro.props;
|
||||
.eyebrow {
|
||||
color: var(--accent);
|
||||
font: var(--font-eyebrow);
|
||||
letter-spacing: .1em;
|
||||
letter-spacing: 0.1em;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ const { eyebrow, title, body, href } = Astro.props;
|
||||
margin: 0;
|
||||
font-size: var(--step-5);
|
||||
line-height: 1.05;
|
||||
letter-spacing: -.06em; /* tight display tracking is a signature of this design */
|
||||
letter-spacing: -0.06em; /* tight display tracking is a signature of this design */
|
||||
}
|
||||
|
||||
p {
|
||||
@@ -69,6 +69,8 @@ const { eyebrow, title, body, href } = Astro.props;
|
||||
}
|
||||
|
||||
@media (max-width: 800px) {
|
||||
.block { padding: 18px; }
|
||||
.block {
|
||||
padding: 18px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
{
|
||||
"extends": ["stylelint-config-standard"],
|
||||
"ignoreFiles": [
|
||||
"dist/**",
|
||||
"public/hands-on/**",
|
||||
"submitted-skills/**"
|
||||
],
|
||||
"ignoreFiles": ["dist/**", "public/hands-on/**", "submitted-skills/**"],
|
||||
"rules": {
|
||||
"custom-property-pattern": "^[a-z][a-z0-9]*(-[a-z0-9]+)*$",
|
||||
"declaration-property-value-disallowed-list": {
|
||||
|
||||
@@ -28,25 +28,30 @@ const lang = 'en'; // TODO: wire to the language toggle decision (task 03)
|
||||
</section>
|
||||
|
||||
<GridGroup label="Chapter sections" columns={3}>
|
||||
{chapter.data.sections.map((section) => (
|
||||
{
|
||||
chapter.data.sections.map((section) => (
|
||||
<StaticBlock
|
||||
eyebrow={section.eyebrow[lang]}
|
||||
title={section.title[lang]}
|
||||
body={section.body[lang]}
|
||||
/>
|
||||
))}
|
||||
))
|
||||
}
|
||||
</GridGroup>
|
||||
</ChapterLayout>
|
||||
|
||||
<style>
|
||||
/* Page-level layout only. Anything reusable belongs in a component. */
|
||||
.hero { max-width: 780px; padding: clamp(75px, 12vh, 145px) 0 85px; }
|
||||
.hero {
|
||||
max-width: 780px;
|
||||
padding: clamp(75px, 12vh, 145px) 0 85px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin: 16px 0 24px;
|
||||
font-size: var(--step-display);
|
||||
line-height: .86;
|
||||
letter-spacing: -.08em;
|
||||
line-height: 0.86;
|
||||
letter-spacing: -0.08em;
|
||||
}
|
||||
|
||||
/* Georgia is a real system font and DOES render — unlike Manrope/DM Mono.
|
||||
@@ -57,5 +62,9 @@ const lang = 'en'; // TODO: wire to the language toggle decision (task 03)
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.lede { max-width: 570px; color: var(--muted); line-height: 1.65; }
|
||||
.lede {
|
||||
max-width: 570px;
|
||||
color: var(--muted);
|
||||
line-height: 1.65;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -39,7 +39,18 @@ const items = entries.map((entry) => ({
|
||||
</BaseLayout>
|
||||
|
||||
<style>
|
||||
.hero { max-width: 780px; padding: clamp(75px, 12vh, 145px) 0 85px; }
|
||||
h1 { font-size: var(--step-display); line-height: .86; letter-spacing: -.08em; }
|
||||
h1 em { color: var(--blue); font-family: Georgia, serif; font-weight: 400; }
|
||||
.hero {
|
||||
max-width: 780px;
|
||||
padding: clamp(75px, 12vh, 145px) 0 85px;
|
||||
}
|
||||
h1 {
|
||||
font-size: var(--step-display);
|
||||
line-height: 0.86;
|
||||
letter-spacing: -0.08em;
|
||||
}
|
||||
h1 em {
|
||||
color: var(--blue);
|
||||
font-family: Georgia, serif;
|
||||
font-weight: 400;
|
||||
}
|
||||
</style>
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"*.{js,mjs,ts,astro}": ["prettier --write", "eslint --fix --max-warnings=0 --no-warn-ignored"],
|
||||
"*.css": ["prettier --write", "stylelint --fix --max-warnings=0"],
|
||||
"*.css": ["prettier --write", "stylelint --fix --max-warnings=0 --allow-empty-input"],
|
||||
"src/**/*.{astro,css}": ["node .agents/scripts/check-tokens.mjs"],
|
||||
"*.{json,md,yml,yaml}": ["prettier --write"]
|
||||
}
|
||||
|
||||
@@ -1,23 +1,37 @@
|
||||
# Gates: review desk privacy and improved-draft audit
|
||||
|
||||
OWNS: skills-review/**, submitted-skills/Anonymous Operational Submission/**, skill-reviews/improved/ndo-repro/**, scripts/verify.mjs
|
||||
OWNS: skills-review/**, submitted-skills/Anonymous Operational Submission/**,
|
||||
skill-reviews/improved/ndo-repro/**, scripts/verify.mjs
|
||||
|
||||
Scope: Redact the operational submission's identity and URLs from the published review desk, keep package files usable in either preview mode, and explain each improved draft as a concrete diff.
|
||||
Scope: Redact the operational submission's identity and URLs from the published
|
||||
review desk, keep package files usable in either preview mode, and explain each
|
||||
improved draft as a concrete diff.
|
||||
|
||||
- [x] G1: the published operational submission contains no personal name, original source URL, email address, or host-specific path
|
||||
CHECK: node scripts/verify.mjs
|
||||
EXPECT: review privacy verification passed
|
||||
EVIDENCE: exit=0; shell=/bin/sh; cwd=/home/marcos/Projects/ai-for-dummies; path=d3551337f830/34 entries; EXPECT=matched; output-sha256=180e8cd0d18968e2a4244ede959c3459b5ce80b836fc5a0df00961907e5d15a1; output-bytes=481
|
||||
- [x] G1: the published operational submission contains no personal name,
|
||||
original source URL, email address, or host-specific path CHECK: node
|
||||
scripts/verify.mjs EXPECT: review privacy verification passed EVIDENCE:
|
||||
exit=0; shell=/bin/sh; cwd=/home/marcos/Projects/ai-for-dummies;
|
||||
path=d3551337f830/34 entries; EXPECT=matched;
|
||||
output-sha256=180e8cd0d18968e2a4244ede959c3459b5ce80b836fc5a0df00961907e5d15a1;
|
||||
output-bytes=481
|
||||
|
||||
- [x] G2: every package file remains selectable in Original and Improved draft modes without resetting the selected preview
|
||||
CHECK: node scripts/verify.mjs
|
||||
EXPECT: review file-mode verification passed
|
||||
EVIDENCE: exit=0; shell=/bin/sh; cwd=/home/marcos/Projects/ai-for-dummies; path=d3551337f830/34 entries; EXPECT=matched; output-sha256=180e8cd0d18968e2a4244ede959c3459b5ce80b836fc5a0df00961907e5d15a1; output-bytes=481
|
||||
- [x] G2: every package file remains selectable in Original and Improved draft
|
||||
modes without resetting the selected preview CHECK: node
|
||||
scripts/verify.mjs EXPECT: review file-mode verification passed EVIDENCE:
|
||||
exit=0; shell=/bin/sh; cwd=/home/marcos/Projects/ai-for-dummies;
|
||||
path=d3551337f830/34 entries; EXPECT=matched;
|
||||
output-sha256=180e8cd0d18968e2a4244ede959c3459b5ce80b836fc5a0df00961907e5d15a1;
|
||||
output-bytes=481
|
||||
|
||||
- [x] G3: every improved draft has an interactive change lens that explains changed guidance and its rationale
|
||||
CHECK: node scripts/verify.mjs
|
||||
EXPECT: review change-lens verification passed
|
||||
EVIDENCE: exit=0; shell=/bin/sh; cwd=/home/marcos/Projects/ai-for-dummies; path=d3551337f830/34 entries; EXPECT=matched; output-sha256=180e8cd0d18968e2a4244ede959c3459b5ce80b836fc5a0df00961907e5d15a1; output-bytes=481
|
||||
- [x] G3: every improved draft has an interactive change lens that explains
|
||||
changed guidance and its rationale CHECK: node scripts/verify.mjs EXPECT:
|
||||
review change-lens verification passed EVIDENCE: exit=0; shell=/bin/sh;
|
||||
cwd=/home/marcos/Projects/ai-for-dummies; path=d3551337f830/34 entries;
|
||||
EXPECT=matched;
|
||||
output-sha256=180e8cd0d18968e2a4244ede959c3459b5ce80b836fc5a0df00961907e5d15a1;
|
||||
output-bytes=481
|
||||
|
||||
- [x] G4: the review desk works at mobile, Full HD, and 4K widths without page errors or horizontal overflow
|
||||
EVIDENCE: Playwright audit on 2026-09-04: 320, 390, 1280, 1920, and 3840px passed with Improved Draft and Change lens rendered; no horizontal overflow or page errors.
|
||||
- [x] G4: the review desk works at mobile, Full HD, and 4K widths without page
|
||||
errors or horizontal overflow EVIDENCE: Playwright audit on 2026-09-04:
|
||||
320, 390, 1280, 1920, and 3840px passed with Improved Draft and Change
|
||||
lens rendered; no horizontal overflow or page errors.
|
||||
|
||||
+88
-1
@@ -1 +1,88 @@
|
||||
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>AI For Dummies — Agents and trees</title><link rel="stylesheet" href="../chapters.css"></head><body><main><header class="top"><a href="../summary/">← ROUTE MAP</a><span>02 / AGENTS & TREES</span><a href="../full-guide/">field guide ↗</a></header><section class="hero"><p class="eyebrow">Subagent workflow</p><h1>One branch<br>per <em>hand.</em></h1><p>Agents work when roles, files, and evidence are bounded. A worktree gives each worker its own checkout while the orchestrator protects intent.</p></section><section class="pipeline"><div><p class="eyebrow">The tree</p><h2>Split at<br>the <em>seam.</em></h2></div><div class="panel"><strong>MAIN / ORCHESTRATOR</strong><code>├── agent/ui → components + visual states · ├── agent/tests → acceptance + regressions · └── agent/docs → guide + examples · merge after each leaf returns a diff and evidence</code></div></section><section class="grid"><article class="card"><b>FRAME</b><h2>Orchestrator</h2><p>Owns scope, task graph, boundaries, and integration.</p></article><article class="card"><b>HAND OFF</b><h2>Worker</h2><p>Owns one coherent slice and one worktree.</p></article><article class="card"><b>PROVE</b><h2>Verifier</h2><p>Re-runs gates and reports remaining gaps.</p></article></section><section class="practice"><div><p class="eyebrow">Handoff</p><h2>Context that<br>can <em>travel.</em></h2></div><div class="steps"><article><b>01</b><div><strong>Brief</strong><span>Goal, owned files, dependencies, non-goals, acceptance.</span></div></article><article><b>02</b><div><strong>Isolation</strong><span>One branch and worktree per independent change.</span></div></article><article><b>03</b><div><strong>Evidence</strong><span>Commands, result, changed files, screenshots, gaps.</span></div></article></div></section><nav class="links"><a href="../models/">Previous: models →</a><a href="../rules/">Rules case study →</a><a href="../hands-on/rules/">Try the rules lab →</a></nav></main></body></html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||
<title>AI For Dummies — Agents and trees</title>
|
||||
<link rel="stylesheet" href="../chapters.css" />
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
<header class="top">
|
||||
<a href="../summary/">← ROUTE MAP</a><span>02 / AGENTS & TREES</span
|
||||
><a href="../full-guide/">field guide ↗</a>
|
||||
</header>
|
||||
<section class="hero">
|
||||
<p class="eyebrow">Subagent workflow</p>
|
||||
<h1>One branch<br />per <em>hand.</em></h1>
|
||||
<p>
|
||||
Agents work when roles, files, and evidence are bounded. A worktree gives each worker its
|
||||
own checkout while the orchestrator protects intent.
|
||||
</p>
|
||||
</section>
|
||||
<section class="pipeline">
|
||||
<div>
|
||||
<p class="eyebrow">The tree</p>
|
||||
<h2>Split at<br />the <em>seam.</em></h2>
|
||||
</div>
|
||||
<div class="panel">
|
||||
<strong>MAIN / ORCHESTRATOR</strong
|
||||
><code
|
||||
>├── agent/ui → components + visual states · ├── agent/tests → acceptance + regressions
|
||||
· └── agent/docs → guide + examples · merge after each leaf returns a diff and
|
||||
evidence</code
|
||||
>
|
||||
</div>
|
||||
</section>
|
||||
<section class="grid">
|
||||
<article class="card">
|
||||
<b>FRAME</b>
|
||||
<h2>Orchestrator</h2>
|
||||
<p>Owns scope, task graph, boundaries, and integration.</p>
|
||||
</article>
|
||||
<article class="card">
|
||||
<b>HAND OFF</b>
|
||||
<h2>Worker</h2>
|
||||
<p>Owns one coherent slice and one worktree.</p>
|
||||
</article>
|
||||
<article class="card">
|
||||
<b>PROVE</b>
|
||||
<h2>Verifier</h2>
|
||||
<p>Re-runs gates and reports remaining gaps.</p>
|
||||
</article>
|
||||
</section>
|
||||
<section class="practice">
|
||||
<div>
|
||||
<p class="eyebrow">Handoff</p>
|
||||
<h2>Context that<br />can <em>travel.</em></h2>
|
||||
</div>
|
||||
<div class="steps">
|
||||
<article>
|
||||
<b>01</b>
|
||||
<div>
|
||||
<strong>Brief</strong
|
||||
><span>Goal, owned files, dependencies, non-goals, acceptance.</span>
|
||||
</div>
|
||||
</article>
|
||||
<article>
|
||||
<b>02</b>
|
||||
<div>
|
||||
<strong>Isolation</strong><span>One branch and worktree per independent change.</span>
|
||||
</div>
|
||||
</article>
|
||||
<article>
|
||||
<b>03</b>
|
||||
<div>
|
||||
<strong>Evidence</strong
|
||||
><span>Commands, result, changed files, screenshots, gaps.</span>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
</section>
|
||||
<nav class="links">
|
||||
<a href="../models/">Previous: models →</a><a href="../rules/">Rules case study →</a
|
||||
><a href="../hands-on/rules/">Try the rules lab →</a>
|
||||
</nav>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
:root{--ink:#122534;--paper:#f6f3ed;--line:#d0d5d2;--muted:#65717a;--blue:#215675;--gold:#ebbf58;--red:#a7483f}*{box-sizing:border-box}body{margin:0;color:var(--ink);background:var(--paper);font:16px/1.6 Arial,sans-serif}main{max-width:1400px;margin:auto;padding:0 5vw}.top{display:flex;justify-content:space-between;gap:20px;padding:24px 0;border-bottom:1px solid var(--line);font:700 11px monospace;letter-spacing:.08em;text-transform:uppercase}.top a{color:var(--ink);text-decoration:none}.hero{padding:100px 0 70px;max-width:950px}.eyebrow{color:var(--red);font:700 11px monospace;letter-spacing:.12em;text-transform:uppercase}.hero h1{margin:16px 0;font-size:clamp(52px,9vw,126px);line-height:.9;letter-spacing:-.07em}.hero h1 em,h2 em{font:400 .9em Georgia,serif;color:var(--red)}.hero p{max-width:680px;color:var(--muted);font-size:20px}.grid{display:grid;grid-template-columns:repeat(3,1fr);gap:1px;background:var(--line);border:1px solid var(--line);margin-bottom:100px}.card{min-height:220px;padding:28px;background:var(--paper)}.card b{color:var(--red);font:24px monospace}.card h2{margin:18px 0 8px;font-size:25px;letter-spacing:-.04em}.card p{margin:0 0 14px;color:var(--muted)}.card a{color:var(--blue);font-weight:700}.model,.pipeline,.practice{display:grid;grid-template-columns:1fr 2fr;gap:50px;padding:80px 0;border-top:1px solid var(--line)}.model h2,.pipeline h2,.practice h2{margin:0;font-size:clamp(34px,5vw,70px);line-height:.95;letter-spacing:-.06em}.panel{padding:28px;background:var(--ink);color:var(--paper)}.panel strong{display:block;color:var(--gold);font:700 12px monospace;letter-spacing:.1em}.panel code{display:block;margin-top:18px;color:#d6e1e4;font:14px/1.8 ui-monospace,monospace;white-space:pre-wrap}.steps{display:grid;gap:1px;background:var(--line)}.steps article{display:grid;grid-template-columns:70px 1fr;gap:20px;padding:20px;background:var(--paper)}.steps b{color:var(--red);font:20px monospace}.steps strong{display:block}.steps span{color:var(--muted)}.links{display:flex;flex-wrap:wrap;gap:10px;margin:28px 0 70px}.links a{padding:10px 13px;color:var(--ink);border:1px solid var(--ink);text-decoration:none;font:11px monospace;text-transform:uppercase}.links a:hover{color:var(--paper);background:var(--ink)}footer{padding:30px 0 70px;color:var(--muted);font-size:13px}@media(max-width:800px){.grid,.model,.pipeline,.practice{grid-template-columns:1fr}.hero{padding:65px 0 45px}.model,.pipeline,.practice{gap:25px;padding:55px 0}}@media(max-width:520px){main{padding:0 16px}.top span{display:none}.hero h1{font-size:56px}.hero p{font-size:17px}.card{min-height:0}.steps article{grid-template-columns:45px 1fr}}
|
||||
:root{--ink:#122534;--paper:#f6f3ed;--line:#d0d5d2;--muted:#65717a;--blue:#215675;--gold:#ebbf58;--red:#a7483f;--font-sans:manrope,arial,sans-serif;--font-mono:'DM Mono',monospace;}*{box-sizing:border-box}body{margin:0;color:var(--ink);background:var(--paper);font:16px/1.6 var(--font-sans)}main{max-width:1400px;margin:auto;padding:0 5vw}.top{display:flex;justify-content:space-between;gap:20px;padding:24px 0;border-bottom:1px solid var(--line);font:700 11px var(--font-mono);letter-spacing:.08em;text-transform:uppercase}.top a{color:var(--ink);text-decoration:none}.hero{padding:100px 0 70px;max-width:950px}.eyebrow{color:var(--red);font:700 11px var(--font-mono);letter-spacing:.12em;text-transform:uppercase}.hero h1{margin:16px 0;font-size:clamp(52px,9vw,126px);line-height:.9;letter-spacing:-.07em}.hero h1 em,h2 em{font:400 .9em Georgia,serif;color:var(--red)}.hero p{max-width:680px;color:var(--muted);font-size:20px}.grid{display:grid;grid-template-columns:repeat(3,1fr);gap:1px;background:var(--line);border:1px solid var(--line);margin-bottom:100px}.card{min-height:220px;padding:28px;background:var(--paper)}.card b{color:var(--red);font:24px var(--font-mono)}.card h2{margin:18px 0 8px;font-size:25px;letter-spacing:-.04em}.card p{margin:0 0 14px;color:var(--muted)}.card a{color:var(--blue);font-weight:700}.model,.pipeline,.practice{display:grid;grid-template-columns:1fr 2fr;gap:50px;padding:80px 0;border-top:1px solid var(--line)}.model h2,.pipeline h2,.practice h2{margin:0;font-size:clamp(34px,5vw,70px);line-height:.95;letter-spacing:-.06em}.panel{padding:28px;background:var(--ink);color:var(--paper)}.panel strong{display:block;color:var(--gold);font:700 12px var(--font-mono);letter-spacing:.1em}.panel code{display:block;margin-top:18px;color:#d6e1e4;font:14px/1.8 var(--font-mono);white-space:pre-wrap}.steps{display:grid;gap:1px;background:var(--line)}.steps article{display:grid;grid-template-columns:70px 1fr;gap:20px;padding:20px;background:var(--paper)}.steps b{color:var(--red);font:20px var(--font-mono)}.steps strong{display:block}.steps span{color:var(--muted)}.links{display:flex;flex-wrap:wrap;gap:10px;margin:28px 0 70px}.links a{padding:10px 13px;color:var(--ink);border:1px solid var(--ink);text-decoration:none;font:11px var(--font-mono);text-transform:uppercase}.links a:hover{color:var(--paper);background:var(--ink)}footer{padding:30px 0 70px;color:var(--muted);font-size:13px}@media(max-width:800px){.grid,.model,.pipeline,.practice{grid-template-columns:1fr}.hero{padding:65px 0 45px}.model,.pipeline,.practice{gap:25px;padding:55px 0}}@media(max-width:520px){main{padding:0 16px}.top span{display:none}.hero h1{font-size:56px}.hero p{font-size:17px}.card{min-height:0}.steps article{grid-template-columns:45px 1fr}}
|
||||
|
||||
+29
-20
@@ -7,38 +7,47 @@ articles are context, not authority.
|
||||
|
||||
- Anthropic — custom subagents: https://code.claude.com/docs/en/sub-agents
|
||||
Separate context, tools, permissions, model selection, and worktree isolation.
|
||||
- Anthropic — skills: https://code.claude.com/docs/en/skills
|
||||
Reusable instruction packages and skill discovery.
|
||||
- Anthropic — worktrees: https://code.claude.com/docs/en/worktrees
|
||||
Isolated sessions, branches, cleanup, and ignored files.
|
||||
- OpenAI — build skills: https://developers.openai.com/codex/skills
|
||||
Packaged instructions and resources for Codex workflows.
|
||||
- OpenAI API — skills reference: https://developers.openai.com/api/reference/go/resources/skills
|
||||
Creating, versioning, listing, and downloading skill bundles.
|
||||
- Git — worktree: https://git-scm.com/docs/git-worktree.html
|
||||
Linked working trees, branches, shared history, add/list/remove/prune.
|
||||
- Anthropic — skills: https://code.claude.com/docs/en/skills Reusable
|
||||
instruction packages and skill discovery.
|
||||
- Anthropic — worktrees: https://code.claude.com/docs/en/worktrees Isolated
|
||||
sessions, branches, cleanup, and ignored files.
|
||||
- OpenAI — build skills: https://developers.openai.com/codex/skills Packaged
|
||||
instructions and resources for Codex workflows.
|
||||
- OpenAI API — skills reference:
|
||||
https://developers.openai.com/api/reference/go/resources/skills Creating,
|
||||
versioning, listing, and downloading skill bundles.
|
||||
- Git — worktree: https://git-scm.com/docs/git-worktree.html Linked working
|
||||
trees, branches, shared history, add/list/remove/prune.
|
||||
|
||||
## Research and articles
|
||||
|
||||
- [Model routing and reasoning controls](model-routing.md) — official OpenAI,
|
||||
Anthropic, and Google terminology, commands, compatibility caveats, and a
|
||||
practical tier/effort baseline.
|
||||
- [Verified skill sources](skill-sources.md) — pinned GitHub references,
|
||||
package paths, local-match confidence, and an approval-first install prompt.
|
||||
- [Verified skill sources](skill-sources.md) — pinned GitHub references, package
|
||||
paths, local-match confidence, and an approval-first install prompt.
|
||||
|
||||
For a structured 12-part reading path—including Git and Anthropic documentation,
|
||||
OpenAI orchestration guidance, Medium, and Substack—see
|
||||
[additional-reading.md](additional-reading.md).
|
||||
|
||||
- Infobip Research — phased coding-agent workflow: https://arxiv.org/abs/2608.30701
|
||||
- Effective asynchronous software engineering agents: https://arxiv.org/abs/2603.21489
|
||||
- Launch Receipts — AI coding workflow without losing control: https://launchreceipts.com/articles/ai-coding-agent-workflow
|
||||
- GitWorktree.org — three agents, three worktrees case study: https://www.gitworktree.org/cases/parallel-ai-agents
|
||||
- Infobip Research — phased coding-agent workflow:
|
||||
https://arxiv.org/abs/2608.30701
|
||||
- Effective asynchronous software engineering agents:
|
||||
https://arxiv.org/abs/2603.21489
|
||||
- Launch Receipts — AI coding workflow without losing control:
|
||||
https://launchreceipts.com/articles/ai-coding-agent-workflow
|
||||
- GitWorktree.org — three agents, three worktrees case study:
|
||||
https://www.gitworktree.org/cases/parallel-ai-agents
|
||||
|
||||
## Teaching claims
|
||||
|
||||
- Use a stronger model where ambiguity, architecture, decomposition, and review dominate.
|
||||
- Use a stronger model where ambiguity, architecture, decomposition, and review
|
||||
dominate.
|
||||
- Use faster models for bounded implementation with explicit context and checks.
|
||||
- Give every editing worker an isolated branch/worktree; merge only reviewed diffs.
|
||||
- A skill is a reusable procedure plus optional references/scripts/assets, not magical memory.
|
||||
- Delegation does not remove human responsibility for intent, boundaries, or evidence.
|
||||
- Give every editing worker an isolated branch/worktree; merge only reviewed
|
||||
diffs.
|
||||
- A skill is a reusable procedure plus optional references/scripts/assets, not
|
||||
magical memory.
|
||||
- Delegation does not remove human responsibility for intent, boundaries, or
|
||||
evidence.
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
# Additional reading: multi-agent coding
|
||||
|
||||
Verified on 2026-09-02. Start with the official references for behavior and constraints; use the practitioner articles for concrete workflow ideas that should be tested against your own repository.
|
||||
Verified on 2026-09-02. Start with the official references for behavior and
|
||||
constraints; use the practitioner articles for concrete workflow ideas that
|
||||
should be tested against your own repository.
|
||||
|
||||
## Git worktrees and isolated coding sessions
|
||||
|
||||
@@ -8,25 +10,38 @@ Verified on 2026-09-02. Start with the official references for behavior and cons
|
||||
|
||||
- **Publisher:** Git
|
||||
- **Topic:** Worktree fundamentals and lifecycle
|
||||
- **Teaching takeaway:** The authoritative reference for how linked worktrees share repository data while retaining separate `HEAD` and index state. Use its `add`, `list`, `lock`, `remove`, `prune`, and `repair` sections to teach the complete lifecycle rather than only worktree creation.
|
||||
- **Teaching takeaway:** The authoritative reference for how linked worktrees
|
||||
share repository data while retaining separate `HEAD` and index state. Use its
|
||||
`add`, `list`, `lock`, `remove`, `prune`, and `repair` sections to teach the
|
||||
complete lifecycle rather than only worktree creation.
|
||||
|
||||
### 2. [Run parallel sessions with worktrees](https://code.claude.com/docs/en/worktrees)
|
||||
|
||||
- **Publisher:** Anthropic — Claude Code Docs
|
||||
- **Topic:** Native worktree isolation for coding agents
|
||||
- **Teaching takeaway:** Shows how Claude Code creates isolated sessions with `--worktree`, how gitignored environment files can be copied with `.worktreeinclude`, and how subagents can use worktree isolation. It is a useful bridge between raw Git commands and a real agent workflow.
|
||||
- **Teaching takeaway:** Shows how Claude Code creates isolated sessions with
|
||||
`--worktree`, how gitignored environment files can be copied with
|
||||
`.worktreeinclude`, and how subagents can use worktree isolation. It is a
|
||||
useful bridge between raw Git commands and a real agent workflow.
|
||||
|
||||
### 3. [How Git Worktrees Transformed My AI Agent Development Workflow in 2026](https://medium.com/@mudassir00seven/how-git-worktrees-transformed-my-ai-agent-development-workflow-in-2026-ad8a59b8edfb)
|
||||
|
||||
- **Publisher:** Medium — Mudassir Khan
|
||||
- **Topic:** One worktree per agent and task
|
||||
- **Teaching takeaway:** A concise practitioner explanation of why parallel agents collide in a shared filesystem and how one task, branch, worktree, and pull request per agent reduces that interference. Pair it with the official Git documentation because operational details may evolve.
|
||||
- **Teaching takeaway:** A concise practitioner explanation of why parallel
|
||||
agents collide in a shared filesystem and how one task, branch, worktree, and
|
||||
pull request per agent reduces that interference. Pair it with the official
|
||||
Git documentation because operational details may evolve.
|
||||
|
||||
### 4. [How to Use Git Worktrees with Coding Agents](https://meshintelligence.substack.com/p/how-to-use-git-worktrees-with-coding)
|
||||
|
||||
- **Publisher:** Mesh Intelligence on Substack — Petar Djukic
|
||||
- **Topic:** Worktree-per-task workflow and integration boundaries
|
||||
- **Teaching takeaway:** Explains why branches alone do not isolate active files, compares worktrees with clones and containers, and presents a create-work-review-remove lifecycle. Its strongest lesson is that worktrees isolate execution, not merge conflicts, so scheduling and review gates still matter.
|
||||
- **Teaching takeaway:** Explains why branches alone do not isolate active
|
||||
files, compares worktrees with clones and containers, and presents a
|
||||
create-work-review-remove lifecycle. Its strongest lesson is that worktrees
|
||||
isolate execution, not merge conflicts, so scheduling and review gates still
|
||||
matter.
|
||||
|
||||
## Subagents and orchestration
|
||||
|
||||
@@ -34,31 +49,48 @@ Verified on 2026-09-02. Start with the official references for behavior and cons
|
||||
|
||||
- **Publisher:** Anthropic — Claude Code Docs
|
||||
- **Topic:** Specialized subagents, context, tools, and background execution
|
||||
- **Teaching takeaway:** Demonstrates how to define narrow subagents with their own prompts, tool permissions, and models, then run them in foreground or background. It supports teaching that delegation quality depends on explicit responsibility and context boundaries, not merely spawning more agents.
|
||||
- **Teaching takeaway:** Demonstrates how to define narrow subagents with their
|
||||
own prompts, tool permissions, and models, then run them in foreground or
|
||||
background. It supports teaching that delegation quality depends on explicit
|
||||
responsibility and context boundaries, not merely spawning more agents.
|
||||
|
||||
### 6. [Building Effective AI Agents](https://www.anthropic.com/engineering/building-effective-agents)
|
||||
|
||||
- **Publisher:** Anthropic Engineering
|
||||
- **Topic:** Agent architecture patterns
|
||||
- **Teaching takeaway:** Introduces routing, parallelization, orchestrator-worker, and evaluator-optimizer patterns while recommending the simplest architecture that meets the task. The orchestrator-worker section is especially useful for explaining when a strong planner should dynamically decompose work for bounded workers.
|
||||
- **Teaching takeaway:** Introduces routing, parallelization,
|
||||
orchestrator-worker, and evaluator-optimizer patterns while recommending the
|
||||
simplest architecture that meets the task. The orchestrator-worker section is
|
||||
especially useful for explaining when a strong planner should dynamically
|
||||
decompose work for bounded workers.
|
||||
|
||||
### 7. [How we built our multi-agent research system](https://www.anthropic.com/engineering/multi-agent-research-system)
|
||||
|
||||
- **Publisher:** Anthropic Engineering
|
||||
- **Topic:** Production multi-agent coordination
|
||||
- **Teaching takeaway:** A production case study in which a lead agent plans and delegates independent searches to parallel subagents. It is useful for discussing breadth-first tasks, separate context windows, token cost, evaluation, and why parallelism helps most when subtasks are genuinely independent.
|
||||
- **Teaching takeaway:** A production case study in which a lead agent plans and
|
||||
delegates independent searches to parallel subagents. It is useful for
|
||||
discussing breadth-first tasks, separate context windows, token cost,
|
||||
evaluation, and why parallelism helps most when subtasks are genuinely
|
||||
independent.
|
||||
|
||||
### 8. [A practical guide to building agents](https://openai.com/business/guides-and-resources/a-practical-guide-to-building-ai-agents/)
|
||||
|
||||
- **Publisher:** OpenAI
|
||||
- **Topic:** Manager and handoff orchestration patterns
|
||||
- **Teaching takeaway:** Distinguishes centralized manager orchestration from decentralized handoffs and shows agents being exposed as tools to other agents. Use it to teach that the right topology depends on who must retain control, combine outputs, and own the final response.
|
||||
- **Teaching takeaway:** Distinguishes centralized manager orchestration from
|
||||
decentralized handoffs and shows agents being exposed as tools to other
|
||||
agents. Use it to teach that the right topology depends on who must retain
|
||||
control, combine outputs, and own the final response.
|
||||
|
||||
### 9. [Agent orchestration](https://openai.github.io/openai-agents-python/multi_agent/)
|
||||
|
||||
- **Publisher:** OpenAI Agents SDK
|
||||
- **Topic:** Agents-as-tools, handoffs, and code-driven workflows
|
||||
- **Teaching takeaway:** Gives a precise comparison between a manager calling specialists as tools and handing control to a specialist. It also covers deterministic orchestration in code, including chains, evaluator loops, and parallel execution for independent tasks.
|
||||
- **Teaching takeaway:** Gives a precise comparison between a manager calling
|
||||
specialists as tools and handing control to a specialist. It also covers
|
||||
deterministic orchestration in code, including chains, evaluator loops, and
|
||||
parallel execution for independent tasks.
|
||||
|
||||
## Model routing and reusable skills
|
||||
|
||||
@@ -66,19 +98,30 @@ Verified on 2026-09-02. Start with the official references for behavior and cons
|
||||
|
||||
- **Publisher:** Anthropic — Claude Platform Docs
|
||||
- **Topic:** Routing work between frontier and lower-cost models
|
||||
- **Teaching takeaway:** Compares model selection, advisor, and orchestrator strategies using cost-per-completed-task rather than token price alone. Its orchestrator guidance directly supports a frontier planner dispatching bulk independent work to cheaper workers—but also explains when one model is simpler and less expensive.
|
||||
- **Teaching takeaway:** Compares model selection, advisor, and orchestrator
|
||||
strategies using cost-per-completed-task rather than token price alone. Its
|
||||
orchestrator guidance directly supports a frontier planner dispatching bulk
|
||||
independent work to cheaper workers—but also explains when one model is
|
||||
simpler and less expensive.
|
||||
|
||||
### 11. [Models](https://openai.github.io/openai-agents-python/models/)
|
||||
|
||||
- **Publisher:** OpenAI Agents SDK
|
||||
- **Topic:** Per-agent model selection and mixed-provider routing
|
||||
- **Teaching takeaway:** Documents how different agents in one workflow can use different models or providers and how routing can be configured centrally. This is a practical implementation reference for turning a conceptual “strong planner, lightweight workers” policy into explicit per-agent configuration.
|
||||
- **Teaching takeaway:** Documents how different agents in one workflow can use
|
||||
different models or providers and how routing can be configured centrally.
|
||||
This is a practical implementation reference for turning a conceptual “strong
|
||||
planner, lightweight workers” policy into explicit per-agent configuration.
|
||||
|
||||
### 12. [Skills](https://platform.claude.com/docs/en/managed-agents/skills)
|
||||
|
||||
- **Publisher:** Anthropic — Claude Platform Docs
|
||||
- **Topic:** Reusable filesystem-based agent skills
|
||||
- **Teaching takeaway:** Explains the `SKILL.md` package model, repository discovery, supporting scripts and resources, and why only task-relevant skills should be attached. It also highlights the security lesson that repository skills are executable instructions and therefore part of the agent’s trust boundary.
|
||||
- **Teaching takeaway:** Explains the `SKILL.md` package model, repository
|
||||
discovery, supporting scripts and resources, and why only task-relevant skills
|
||||
should be attached. It also highlights the security lesson that repository
|
||||
skills are executable instructions and therefore part of the agent’s trust
|
||||
boundary.
|
||||
|
||||
## Suggested teaching order
|
||||
|
||||
|
||||
@@ -1,25 +1,42 @@
|
||||
# Model routing and reasoning controls
|
||||
|
||||
Verified against first-party documentation on 2026-09-02. Model catalogs and aliases change; pin production model IDs and re-check the linked compatibility tables before rollout.
|
||||
Verified against first-party documentation on 2026-09-02. Model catalogs and
|
||||
aliases change; pin production model IDs and re-check the linked compatibility
|
||||
tables before rollout.
|
||||
|
||||
## Two independent routing knobs
|
||||
|
||||
1. **Model tier** chooses the capability, latency, and cost envelope.
|
||||
2. **Effort / thinking control** changes how much reasoning work a supported model performs for one request.
|
||||
2. **Effort / thinking control** changes how much reasoning work a supported
|
||||
model performs for one request.
|
||||
|
||||
Do not assume that every effort value works with every model or product. Unsupported values may fail, be ignored, or be mapped to another level depending on the client.
|
||||
Do not assume that every effort value works with every model or product.
|
||||
Unsupported values may fail, be ignored, or be mapped to another level depending
|
||||
on the client.
|
||||
|
||||
## OpenAI
|
||||
|
||||
The current GPT-5.6 family exposes the **Sol**, **Terra**, and **Luna** model tiers. Its documented `reasoning.effort` values are `none`, `low`, `medium`, `high`, `xhigh`, and `max`. Availability remains model-specific, so select from the levels shown for the chosen model rather than treating the full list as universal. [OpenAI: latest model guide](https://developers.openai.com/api/docs/guides/latest-model)
|
||||
The current GPT-5.6 family exposes the **Sol**, **Terra**, and **Luna** model
|
||||
tiers. Its documented `reasoning.effort` values are `none`, `low`, `medium`,
|
||||
`high`, `xhigh`, and `max`. Availability remains model-specific, so select from
|
||||
the levels shown for the chosen model rather than treating the full list as
|
||||
universal.
|
||||
[OpenAI: latest model guide](https://developers.openai.com/api/docs/guides/latest-model)
|
||||
|
||||
Use a lower-cost tier and low effort for bounded, mechanical work; raise the model tier or effort for planning, architecture, difficult debugging, and final review. This is routing guidance, not an API guarantee.
|
||||
Use a lower-cost tier and low effort for bounded, mechanical work; raise the
|
||||
model tier or effort for planning, architecture, difficult debugging, and final
|
||||
review. This is routing guidance, not an API guarantee.
|
||||
|
||||
## Anthropic Claude
|
||||
|
||||
### Model tier
|
||||
|
||||
Claude Code provides the aliases `opus`, `sonnet`, and `haiku`: Opus is intended for complex reasoning, Sonnet for everyday coding, and Haiku for simple, fast work. Aliases resolve to provider-dependent recommended versions and can change over time; use a full model ID when reproducibility matters. Claude Code also documents `opusplan`, which uses Opus in plan mode and Sonnet for execution. [Claude Code: model configuration](https://docs.anthropic.com/en/docs/claude-code/model-config)
|
||||
Claude Code provides the aliases `opus`, `sonnet`, and `haiku`: Opus is intended
|
||||
for complex reasoning, Sonnet for everyday coding, and Haiku for simple, fast
|
||||
work. Aliases resolve to provider-dependent recommended versions and can change
|
||||
over time; use a full model ID when reproducibility matters. Claude Code also
|
||||
documents `opusplan`, which uses Opus in plan mode and Sonnet for execution.
|
||||
[Claude Code: model configuration](https://docs.anthropic.com/en/docs/claude-code/model-config)
|
||||
|
||||
Copy-ready Claude Code switches:
|
||||
|
||||
@@ -37,7 +54,12 @@ claude --model opus
|
||||
|
||||
### Effort
|
||||
|
||||
The Claude API parameter is `output_config.effort`. The documented levels are `low`, `medium`, `high`, `xhigh`, and `max`; `high` is the API default. `xhigh` and `max` have narrower model support, and Haiku 4.5 does not support effort. Effort affects the whole response—including thinking and tool calls—and is a behavioral signal, not a strict token budget. [Anthropic: effort](https://docs.anthropic.com/en/docs/build-with-claude/effort)
|
||||
The Claude API parameter is `output_config.effort`. The documented levels are
|
||||
`low`, `medium`, `high`, `xhigh`, and `max`; `high` is the API default. `xhigh`
|
||||
and `max` have narrower model support, and Haiku 4.5 does not support effort.
|
||||
Effort affects the whole response—including thinking and tool calls—and is a
|
||||
behavioral signal, not a strict token budget.
|
||||
[Anthropic: effort](https://docs.anthropic.com/en/docs/build-with-claude/effort)
|
||||
|
||||
Documented Python example:
|
||||
|
||||
@@ -53,27 +75,45 @@ response = client.messages.create(
|
||||
)
|
||||
```
|
||||
|
||||
Claude Code exposes `/effort`; its available choices depend on the active model. Current Claude Code documentation lists `low`, `medium`, `high`, `xhigh`, and `max` for supported Opus versions, while some Opus/Sonnet versions omit `xhigh`. When a selected level is unsupported, Claude Code can fall back to the highest supported level at or below it. [Claude Code: effort compatibility](https://docs.anthropic.com/en/docs/claude-code/model-config#adjust-effort-level)
|
||||
Claude Code exposes `/effort`; its available choices depend on the active model.
|
||||
Current Claude Code documentation lists `low`, `medium`, `high`, `xhigh`, and
|
||||
`max` for supported Opus versions, while some Opus/Sonnet versions omit `xhigh`.
|
||||
When a selected level is unsupported, Claude Code can fall back to the highest
|
||||
supported level at or below it.
|
||||
[Claude Code: effort compatibility](https://docs.anthropic.com/en/docs/claude-code/model-config#adjust-effort-level)
|
||||
|
||||
## Google Gemini
|
||||
|
||||
### Model tier
|
||||
|
||||
Gemini uses model families rather than interchangeable aliases: **Pro** targets the most complex reasoning, **Flash** balances capability and throughput, and **Flash-Lite** prioritizes latency, volume, and cost. Select an explicit endpoint such as `gemini-3.7-flash`; Google recommends stable model names for most production applications because `latest` aliases can be hot-swapped. [Gemini API: models](https://ai.google.dev/gemini-api/docs/models)
|
||||
Gemini uses model families rather than interchangeable aliases: **Pro** targets
|
||||
the most complex reasoning, **Flash** balances capability and throughput, and
|
||||
**Flash-Lite** prioritizes latency, volume, and cost. Select an explicit
|
||||
endpoint such as `gemini-3.7-flash`; Google recommends stable model names for
|
||||
most production applications because `latest` aliases can be hot-swapped.
|
||||
[Gemini API: models](https://ai.google.dev/gemini-api/docs/models)
|
||||
|
||||
### Thinking level
|
||||
|
||||
For Gemini 3 models, the control is `thinkingLevel` in SDKs (`thinking_level` in Python). Across the family the documented values are `minimal`, `low`, `medium`, and `high`, but support and defaults vary by model. For example, Gemini 3.7 Flash supports `low`, `medium`, and `high` and defaults to `medium`; Gemini 3.1 Pro supports `low`, `medium`, and `high` and defaults to `high`. `minimal` is unavailable on several models and does not guarantee that reasoning is completely off where supported. Gemini 2.5 uses `thinkingBudget`, not `thinkingLevel`. [Gemini API: thinking](https://ai.google.dev/gemini-api/docs/thinking)
|
||||
For Gemini 3 models, the control is `thinkingLevel` in SDKs (`thinking_level` in
|
||||
Python). Across the family the documented values are `minimal`, `low`, `medium`,
|
||||
and `high`, but support and defaults vary by model. For example, Gemini 3.7
|
||||
Flash supports `low`, `medium`, and `high` and defaults to `medium`; Gemini 3.1
|
||||
Pro supports `low`, `medium`, and `high` and defaults to `high`. `minimal` is
|
||||
unavailable on several models and does not guarantee that reasoning is
|
||||
completely off where supported. Gemini 2.5 uses `thinkingBudget`, not
|
||||
`thinkingLevel`.
|
||||
[Gemini API: thinking](https://ai.google.dev/gemini-api/docs/thinking)
|
||||
|
||||
Documented JavaScript pattern:
|
||||
|
||||
```javascript
|
||||
import { GoogleGenAI, ThinkingLevel } from "@google/genai";
|
||||
import { GoogleGenAI, ThinkingLevel } from '@google/genai';
|
||||
|
||||
const ai = new GoogleGenAI({});
|
||||
const response = await ai.models.generateContent({
|
||||
model: "gemini-3.7-flash",
|
||||
contents: "Review this implementation plan.",
|
||||
model: 'gemini-3.7-flash',
|
||||
contents: 'Review this implementation plan.',
|
||||
config: {
|
||||
thinkingConfig: {
|
||||
thinkingLevel: ThinkingLevel.LOW,
|
||||
@@ -87,10 +127,12 @@ console.log(response.text);
|
||||
## Practical routing baseline
|
||||
|
||||
| Work | Model tier | Effort / thinking |
|
||||
| --- | --- | --- |
|
||||
| --------------------------------------------------- | ------------------------- | -------------------------------------- |
|
||||
| Formatting, lookup, narrow edit | Haiku / Flash-Lite / Luna | Low or minimal where supported |
|
||||
| Normal implementation, tests, review | Sonnet / Flash / Terra | Medium |
|
||||
| Architecture, orchestration, hard debugging | Opus / Pro / Sol | High |
|
||||
| Frontier or long-horizon work with measured benefit | Strongest supported tier | `xhigh` or `max` only where documented |
|
||||
|
||||
Treat this table as a starting hypothesis. Evaluate quality, latency, and cost on representative tasks, then route to the cheapest combination that still passes the required checks.
|
||||
Treat this table as a starting hypothesis. Evaluate quality, latency, and cost
|
||||
on representative tasks, then route to the cheapest combination that still
|
||||
passes the required checks.
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
# Verified skill sources
|
||||
|
||||
Checked on 2026-09-02 against the installed files under `~/.codex/skills`. A pinned blob link identifies the content inspected; the repository/path column identifies what an installer should copy. Pinned commits are preferable to mutable `main` when reproducibility matters.
|
||||
Checked on 2026-09-02 against the installed files under `~/.codex/skills`. A
|
||||
pinned blob link identifies the content inspected; the repository/path column
|
||||
identifies what an installer should copy. Pinned commits are preferable to
|
||||
mutable `main` when reproducibility matters.
|
||||
|
||||
| Skill | Verified source URL | Installable repo URL/path | Confidence / note |
|
||||
|---|---|---|---|
|
||||
| ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `ponytail-lite` | [`AGENTS.md` at `e7b42dc`](https://github.com/ilindaniel/ponytail-lite/blob/e7b42dc2d384a702240dea4d52a7bf5530b821b6/AGENTS.md) | [`ilindaniel/ponytail-lite`](https://github.com/ilindaniel/ponytail-lite), path `AGENTS.md` | **High — exact byte match.** The local `ponytail-lite/SKILL.md` is this file unchanged. Upstream presents it as an agent instruction file, not a conventional frontmatter-based skill package; install it through the host's project/global instruction mechanism. |
|
||||
| `caveman` | [Public upstream skill at `3b74643`](https://github.com/JuliusBrussee/caveman/blob/3b74643f4d910f496babd4e634b1ba7168816f14/skills/caveman/SKILL.md) | [`JuliusBrussee/caveman`](https://github.com/JuliusBrussee/caveman), path `skills/caveman/` | **Medium for the installed file; high for upstream.** The local file is an environment-specific wrapper that names this public project and its skill files, but it is not byte-identical to the public `skills/caveman/SKILL.md`. Install upstream, not the local wrapper. |
|
||||
| `unlazy` | [`SKILL.md` at `473d4b8`](https://github.com/Leonxlnx/unlazy/blob/473d4b80421c36d733042434cd4b938f81a19ef1/SKILL.md) | [`Leonxlnx/unlazy`](https://github.com/Leonxlnx/unlazy), repository root (copy the whole package) | **High — exact byte match**, also corroborated by local `.unlazy-source.txt`. The package includes referenced scripts, templates, security notes, and workflow documents; do not copy only `SKILL.md`. |
|
||||
@@ -38,4 +41,8 @@ Workflow:
|
||||
|
||||
## Verification method
|
||||
|
||||
The seven **exact** findings were established by downloading the pinned public files and comparing them byte-for-byte with the local installed copies. For `caveman`, the local wrapper was compared against both the repository-level instructions and public `skills/caveman/SKILL.md`; neither matched, so only its upstream family is attributed, not the wrapper itself.
|
||||
The seven **exact** findings were established by downloading the pinned public
|
||||
files and comparing them byte-for-byte with the local installed copies. For
|
||||
`caveman`, the local wrapper was compared against both the repository-level
|
||||
instructions and public `skills/caveman/SKILL.md`; neither matched, so only its
|
||||
upstream family is attributed, not the wrapper itself.
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
.handoff thead{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0)}
|
||||
.handoff tbody tr{padding:14px 0;border-bottom:1px solid var(--line)}
|
||||
.handoff th,.handoff td{padding:4px 0;border:0}
|
||||
.handoff td::before{display:block;margin-top:7px;color:var(--blue);font:600 9px 'DM Mono',monospace;letter-spacing:.08em;text-transform:uppercase}
|
||||
.handoff td::before{display:block;margin-top:7px;color:var(--blue);font:600 9px var(--font-mono);letter-spacing:.08em;text-transform:uppercase}
|
||||
.handoff td:nth-child(2)::before{content:'Contains'}
|
||||
.handoff td:nth-child(3)::before{content:'Why it matters'}
|
||||
.route-table .head{display:none}
|
||||
|
||||
+68
-16
@@ -1,27 +1,79 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
||||
<meta name="description" content="AI For Dummies: a practical route map for models, agents, worktrees, skills, rules, and verification.">
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||
<meta
|
||||
name="description"
|
||||
content="AI For Dummies: a practical route map for models, agents, worktrees, skills, rules, and verification."
|
||||
/>
|
||||
<title>AI For Dummies — Start here</title>
|
||||
<link rel="stylesheet" href="chapters.css">
|
||||
<link rel="stylesheet" href="landing.css">
|
||||
<link rel="stylesheet" href="chapters.css" />
|
||||
<link rel="stylesheet" href="landing.css" />
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
<header class="top"><a href="./" aria-current="page">AI FOR DUMMIES</a><span>00 / START HERE</span><a href="skills-review/">review desk ↗</a></header>
|
||||
<section class="hero"><p class="eyebrow">The short route</p><h1>Ship the<br><em>system.</em></h1><p>Start with the map. Then open the one chapter that matches the decision in front of you: model, agent, worktree, skill, rule, or proof.</p><a class="guide-launch" href="full-guide/">Take the full field guide <span>→</span></a></section>
|
||||
<section class="grid route-grid" aria-label="Guide chapters">
|
||||
<article class="card"><b>01</b><h2>Models</h2><p>Capability and effort are separate knobs.</p><a href="models/">Open chapter →</a></article>
|
||||
<article class="card"><b>02</b><h2>Agents & trees</h2><p>Bound roles, handoffs, and worktrees.</p><a href="agents/">Open chapter →</a></article>
|
||||
<article class="card"><b>03</b><h2>Skills</h2><p>Capture repeatable decisions in small packages.</p><a href="skills/">Open chapter →</a></article>
|
||||
<article class="card"><b>04</b><h2>Rules</h2><p>Connect guidance to enforcement.</p><a href="rules/">Open chapter →</a></article>
|
||||
<article class="card"><b>05</b><h2>Hands-on</h2><p>Compare a strong prompt with skill-enabled work.</p><a href="hands-on/starter/">Open lab →</a></article>
|
||||
<article class="card"><b>06</b><h2>Review desk</h2><p>Browse original packages, references, scripts, and improvements.</p><a href="skills-review/">Open desk →</a></article>
|
||||
<header class="top">
|
||||
<a href="./" aria-current="page">AI FOR DUMMIES</a><span>00 / START HERE</span
|
||||
><a href="skills-review/">review desk ↗</a>
|
||||
</header>
|
||||
<section class="hero">
|
||||
<p class="eyebrow">The short route</p>
|
||||
<h1>Ship the<br /><em>system.</em></h1>
|
||||
<p>
|
||||
Start with the map. Then open the one chapter that matches the decision in front of you:
|
||||
model, agent, worktree, skill, rule, or proof.
|
||||
</p>
|
||||
<a class="guide-launch" href="full-guide/">Take the full field guide <span>→</span></a>
|
||||
</section>
|
||||
<section class="landing-note"><span>THE THREAD</span><strong>Frame uncertainty → isolate execution → preserve judgment → verify the change.</strong></section>
|
||||
<footer>The route map is now the default entry. The full guide remains available whenever you want the whole narrative.</footer>
|
||||
<section class="grid route-grid" aria-label="Guide chapters">
|
||||
<article class="card">
|
||||
<b>01</b>
|
||||
<h2>Models</h2>
|
||||
<p>Capability and effort are separate knobs.</p>
|
||||
<a href="models/">Open chapter →</a>
|
||||
</article>
|
||||
<article class="card">
|
||||
<b>02</b>
|
||||
<h2>Agents & trees</h2>
|
||||
<p>Bound roles, handoffs, and worktrees.</p>
|
||||
<a href="agents/">Open chapter →</a>
|
||||
</article>
|
||||
<article class="card">
|
||||
<b>03</b>
|
||||
<h2>Skills</h2>
|
||||
<p>Capture repeatable decisions in small packages.</p>
|
||||
<a href="skills/">Open chapter →</a>
|
||||
</article>
|
||||
<article class="card">
|
||||
<b>04</b>
|
||||
<h2>Rules</h2>
|
||||
<p>Connect guidance to enforcement.</p>
|
||||
<a href="rules/">Open chapter →</a>
|
||||
</article>
|
||||
<article class="card">
|
||||
<b>05</b>
|
||||
<h2>Hands-on</h2>
|
||||
<p>Compare a strong prompt with skill-enabled work.</p>
|
||||
<a href="hands-on/starter/">Open lab →</a>
|
||||
</article>
|
||||
<article class="card">
|
||||
<b>06</b>
|
||||
<h2>Review desk</h2>
|
||||
<p>Browse original packages, references, scripts, and improvements.</p>
|
||||
<a href="skills-review/">Open desk →</a>
|
||||
</article>
|
||||
</section>
|
||||
<section class="landing-note">
|
||||
<span>THE THREAD</span
|
||||
><strong
|
||||
>Frame uncertainty → isolate execution → preserve judgment → verify the change.</strong
|
||||
>
|
||||
</section>
|
||||
<footer>
|
||||
The route map is now the default entry. The full guide remains available whenever you want
|
||||
the whole narrative.
|
||||
</footer>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
.guide-launch{display:inline-flex;gap:14px;align-items:center;margin-top:20px;padding:12px 16px;background:var(--ink);color:var(--paper);font:700 12px ui-monospace,monospace;letter-spacing:.06em;text-decoration:none;text-transform:uppercase;transition:transform .2s ease,background .2s ease}.guide-launch:hover{transform:translateY(-3px);background:var(--blue)}.guide-launch span{color:var(--gold);font-size:22px;line-height:0}.route-grid .card{display:flex;min-width:0;flex-direction:column}.route-grid .card a{margin-top:auto}.landing-note{display:grid;grid-template-columns:170px minmax(0,1fr);gap:30px;margin:0 0 70px;padding:25px 0;border-top:1px solid var(--ink);border-bottom:1px solid var(--ink)}.landing-note span{color:var(--red);font:700 11px ui-monospace,monospace;letter-spacing:.1em}.landing-note strong{font-size:clamp(22px,3.2vw,42px);line-height:1.08;letter-spacing:-.04em}@media(max-width:520px){.landing-note{grid-template-columns:1fr;gap:9px;margin-bottom:45px}}@media(prefers-reduced-motion:reduce){.guide-launch{transition:none}.guide-launch:hover{transform:none}}
|
||||
.guide-launch{display:inline-flex;gap:14px;align-items:center;margin-top:20px;padding:12px 16px;background:var(--ink);color:var(--paper);font:700 12px var(--font-mono);letter-spacing:.06em;text-decoration:none;text-transform:uppercase;transition:transform .2s ease,background .2s ease}.guide-launch:hover{transform:translateY(-3px);background:var(--blue)}.guide-launch span{color:var(--gold);font-size:22px;line-height:0}.route-grid .card{display:flex;min-width:0;flex-direction:column}.route-grid .card a{margin-top:auto}.landing-note{display:grid;grid-template-columns:170px minmax(0,1fr);gap:30px;margin:0 0 70px;padding:25px 0;border-top:1px solid var(--ink);border-bottom:1px solid var(--ink)}.landing-note span{color:var(--red);font:700 11px var(--font-mono);letter-spacing:.1em}.landing-note strong{font-size:clamp(22px,3.2vw,42px);line-height:1.08;letter-spacing:-.04em}@media(max-width:520px){.landing-note{grid-template-columns:1fr;gap:9px;margin-bottom:45px}}@media(prefers-reduced-motion:reduce){.guide-launch{transition:none}.guide-launch:hover{transform:none}}
|
||||
|
||||
+87
-1
@@ -1 +1,87 @@
|
||||
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>AI For Dummies — Models</title><link rel="stylesheet" href="../chapters.css"></head><body><main><header class="top"><a href="../summary/">← ROUTE MAP</a><span>01 / MODELS</span><a href="../full-guide/">field guide ↗</a></header><section class="hero"><p class="eyebrow">Model routing</p><h1>Choose the<br><em>engine.</em></h1><p>A model has a capability ceiling. Effort controls how much room it gets to reason. Route by uncertainty and verification cost.</p></section><section class="grid"><article class="card"><b>LOW</b><h2>Bounded rhythm</h2><p>Lookup, small edits, formatting, and transformations with clear checks.</p></article><article class="card"><b>MEDIUM</b><h2>Default work</h2><p>Normal implementation where the contract is clear but context matters.</p></article><article class="card"><b>HIGH</b><h2>Ambiguity</h2><p>Planning, architecture, security judgment, and hard failures.</p></article></section><section class="model"><div><p class="eyebrow">Two knobs</p><h2>Capability<br>× effort</h2></div><div class="panel"><strong>ROUTING RULE</strong><code>strong model + high effort → frame ambiguity · light model + low effort → bounded execution · raise one knob at a time → compare evidence</code></div></section><section class="practice"><div><p class="eyebrow">Sequence</p><h2>Spend judgment<br>where it <em>compounds.</em></h2></div><div class="steps"><article><b>01</b><div><strong>Plan</strong><span>Strong model: scope, risks, acceptance, and worktree split.</span></div></article><article><b>02</b><div><strong>Build</strong><span>Focused worker: smallest context and lightest model that can pass.</span></div></article><article><b>03</b><div><strong>Review</strong><span>Independent pass when missed issues cost more than the call.</span></div></article></div></section><nav class="links"><a href="../agents/">Next: agents & trees →</a><a href="../rules/">Rules case study →</a></nav></main></body></html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||
<title>AI For Dummies — Models</title>
|
||||
<link rel="stylesheet" href="../chapters.css" />
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
<header class="top">
|
||||
<a href="../summary/">← ROUTE MAP</a><span>01 / MODELS</span
|
||||
><a href="../full-guide/">field guide ↗</a>
|
||||
</header>
|
||||
<section class="hero">
|
||||
<p class="eyebrow">Model routing</p>
|
||||
<h1>Choose the<br /><em>engine.</em></h1>
|
||||
<p>
|
||||
A model has a capability ceiling. Effort controls how much room it gets to reason. Route
|
||||
by uncertainty and verification cost.
|
||||
</p>
|
||||
</section>
|
||||
<section class="grid">
|
||||
<article class="card">
|
||||
<b>LOW</b>
|
||||
<h2>Bounded rhythm</h2>
|
||||
<p>Lookup, small edits, formatting, and transformations with clear checks.</p>
|
||||
</article>
|
||||
<article class="card">
|
||||
<b>MEDIUM</b>
|
||||
<h2>Default work</h2>
|
||||
<p>Normal implementation where the contract is clear but context matters.</p>
|
||||
</article>
|
||||
<article class="card">
|
||||
<b>HIGH</b>
|
||||
<h2>Ambiguity</h2>
|
||||
<p>Planning, architecture, security judgment, and hard failures.</p>
|
||||
</article>
|
||||
</section>
|
||||
<section class="model">
|
||||
<div>
|
||||
<p class="eyebrow">Two knobs</p>
|
||||
<h2>Capability<br />× effort</h2>
|
||||
</div>
|
||||
<div class="panel">
|
||||
<strong>ROUTING RULE</strong
|
||||
><code
|
||||
>strong model + high effort → frame ambiguity · light model + low effort → bounded
|
||||
execution · raise one knob at a time → compare evidence</code
|
||||
>
|
||||
</div>
|
||||
</section>
|
||||
<section class="practice">
|
||||
<div>
|
||||
<p class="eyebrow">Sequence</p>
|
||||
<h2>Spend judgment<br />where it <em>compounds.</em></h2>
|
||||
</div>
|
||||
<div class="steps">
|
||||
<article>
|
||||
<b>01</b>
|
||||
<div>
|
||||
<strong>Plan</strong
|
||||
><span>Strong model: scope, risks, acceptance, and worktree split.</span>
|
||||
</div>
|
||||
</article>
|
||||
<article>
|
||||
<b>02</b>
|
||||
<div>
|
||||
<strong>Build</strong
|
||||
><span>Focused worker: smallest context and lightest model that can pass.</span>
|
||||
</div>
|
||||
</article>
|
||||
<article>
|
||||
<b>03</b>
|
||||
<div>
|
||||
<strong>Review</strong
|
||||
><span>Independent pass when missed issues cost more than the call.</span>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
</section>
|
||||
<nav class="links">
|
||||
<a href="../agents/">Next: agents & trees →</a><a href="../rules/">Rules case study →</a>
|
||||
</nav>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
# Task 05 — Guide content out of app.js
|
||||
|
||||
**Agent**: `content-i18n-migrator` · **Model**: MiniMax-M3
|
||||
**Depends on**: 04 · **Parallel with**: 06 · **Blocks**: 15
|
||||
**Worktree**: `.agents/scripts/worktree.sh start 05 content-guide`
|
||||
**Agent**: `content-i18n-migrator` · **Model**: MiniMax-M3 **Depends on**: 04 ·
|
||||
**Parallel with**: 06 · **Blocks**: 15 **Worktree**:
|
||||
`.agents/scripts/worktree.sh start 05 content-guide`
|
||||
|
||||
## Goal
|
||||
|
||||
Every `{ en, pt }` string in `app.js` lives in `src/content/guide/`, byte-identical.
|
||||
Every `{ en, pt }` string in `app.js` lives in `src/content/guide/`,
|
||||
byte-identical.
|
||||
|
||||
## Scope
|
||||
|
||||
@@ -15,13 +16,13 @@ removes it once the page consumes the collection.
|
||||
|
||||
## Steps
|
||||
|
||||
1. `node .agents/scripts/extract-strings.mjs app.js > /tmp/before.json`
|
||||
(~50 pairs across `phases`, `handsOnPrompts`, `modelGuide`, `skillSources`,
|
||||
1. `node .agents/scripts/extract-strings.mjs app.js > /tmp/before.json` (~50
|
||||
pairs across `phases`, `handsOnPrompts`, `modelGuide`, `skillSources`,
|
||||
`skillInstallPrompts`).
|
||||
2. Move them into the collection. **Copy mechanically — never retype.** These
|
||||
are hand-written translations with deliberate tone (`'Transforme ambiguidade
|
||||
em trabalho'`); retyping introduces drift nobody catches until a Portuguese
|
||||
speaker reads it.
|
||||
are hand-written translations with deliberate tone
|
||||
(`'Transforme ambiguidade em trabalho'`); retyping introduces drift nobody
|
||||
catches until a Portuguese speaker reads it.
|
||||
3. `node .agents/scripts/extract-strings.mjs src/content/guide/ > /tmp/after.json`
|
||||
4. `diff /tmp/before.json /tmp/after.json` → **must be empty**.
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# Task 06 — Review-desk content out of catalog.js
|
||||
|
||||
**Agent**: `content-i18n-migrator` · **Model**: MiniMax-M3
|
||||
**Depends on**: 04 · **Parallel with**: 05 · **Blocks**: 16
|
||||
**Worktree**: `.agents/scripts/worktree.sh start 06 content-review`
|
||||
**Agent**: `content-i18n-migrator` · **Model**: MiniMax-M3 **Depends on**: 04 ·
|
||||
**Parallel with**: 05 · **Blocks**: 16 **Worktree**:
|
||||
`.agents/scripts/worktree.sh start 06 content-review`
|
||||
|
||||
## Goal
|
||||
|
||||
@@ -32,12 +32,14 @@ real `.md` files.
|
||||
node scripts/build-skill-review.mjs && git diff --exit-code skill-reviews/
|
||||
```
|
||||
2. **The diff view needs raw source.** The review desk compares original and
|
||||
improved as *text*. If `improved` only exists as rendered HTML, the change
|
||||
improved as _text_. If `improved` only exists as rendered HTML, the change
|
||||
lens breaks. Keep the raw string reachable.
|
||||
|
||||
## Done when
|
||||
|
||||
- [ ] 24 entries in the collection; `verify.mjs`'s `id:'` count assertion still passes
|
||||
- [ ] 24 entries in the collection; `verify.mjs`'s `id:'` count assertion still
|
||||
passes
|
||||
- [ ] `git diff --exit-code skill-reviews/` clean after regenerating
|
||||
- [ ] `astro check` passes
|
||||
- [ ] Every reference to the generator still accurate (`package.json`, `README.md`, `docs/operations-guide.md`, the review desk footer)
|
||||
- [ ] Every reference to the generator still accurate (`package.json`,
|
||||
`README.md`, `docs/operations-guide.md`, the review desk footer)
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
# Task 10b — Locale-paired props on the six full-guide blocks
|
||||
|
||||
**Agent**: `component-builder` · **Model**: **Codex** **Depends on**: 10 ·
|
||||
**Blocks**: 15d **Worktree**:
|
||||
`.agents/scripts/worktree.sh start 10b bilingual-blocks`
|
||||
|
||||
## Why this task exists
|
||||
|
||||
It is not in the original plan. Tasks 07–11 built the primitives and blocks
|
||||
before task 15c wrote the language contract, so every prose prop on all 19
|
||||
blocks is a plain `string`. Task 15d then stopped, correctly, when it found it
|
||||
could not render `/full-guide/` in both languages: the brief forbids it from
|
||||
duplicating a block to get a second locale, and changing a block's interface is
|
||||
component-builder work, not page-migrator work.
|
||||
|
||||
`/full-guide/` is one of only two pages with a language toggle (the other is
|
||||
`/rules/`, which is already fully bilingual — all 23 of its Portuguese strings
|
||||
reach the built page, because `RulesInteractive` reads them from
|
||||
`src/content/rules/stages.json` and swaps client-side). The five remaining pages
|
||||
have no toggle today and must not gain one.
|
||||
|
||||
## Scope
|
||||
|
||||
Exactly six files, all in `src/components/blocks/`:
|
||||
|
||||
`FleetDiagram.astro`, `HandoffTable.astro`, `PhasePanel.astro`,
|
||||
`RouteTable.astro`, `SkillPackage.astro`, `WorktreeMap.astro`.
|
||||
|
||||
These are the six that `src/pages/full-guide.astro` uses. Do not touch the other
|
||||
13 blocks, any primitive, any island, or any page.
|
||||
|
||||
## What to change
|
||||
|
||||
Every **prose** prop on those six accepts `Localized` as well as `string`:
|
||||
|
||||
```ts
|
||||
type Localized = { en: string; pt: string };
|
||||
```
|
||||
|
||||
- Given a `string`, render exactly what it renders today. Every existing call
|
||||
site keeps working untouched — this is additive.
|
||||
- Given a `Localized`, render the fragment twice per
|
||||
`.agents/context/content-i18n.md`: `data-language-content="en"` on one and
|
||||
`"pt"` on the other, English visible, Portuguese `hidden`.
|
||||
|
||||
Prose only. Do not widen `href`, `id`, `code`, numeric or enum props — several
|
||||
are deliberately unlocalized, and task 05b recorded which (`trees.path`,
|
||||
`trees.command`, `routes.score`, `commonSkills.source`).
|
||||
|
||||
`FleetDiagram`'s `orchestrator.title` is rendered with `set:html` because it
|
||||
carries inline `<br>`. Keep that, on both locales.
|
||||
|
||||
## Do not
|
||||
|
||||
- Do not change what a block renders for a `string` prop. A diff in the built
|
||||
output for the existing call sites means you got it wrong.
|
||||
- Do not add a language toggle to any block. `LanguageToggle` is a separate
|
||||
island and the page mounts it.
|
||||
- Do not edit `scripts/verify.mjs`. 42 assertions, and you are not the
|
||||
verification-engineer.
|
||||
- Do not touch `src/pages/full-guide.astro`. That is 15d's file; it will pass
|
||||
the `Localized` values once you land.
|
||||
|
||||
## Done when
|
||||
|
||||
- [ ] All six blocks accept `Localized` on every prose prop and `string` still
|
||||
behaves identically
|
||||
- [ ] Built output byte-identical for pages that pass only strings — check
|
||||
`dist/` before and after for the pages that use these blocks
|
||||
- [ ] `pnpm run gate` green, 42 assertions intact
|
||||
- [ ] Report lists, per block, which props became locale-aware and which you
|
||||
deliberately left unlocalized and why
|
||||
@@ -130,3 +130,202 @@ They are yours. Lift them verbatim — same rule as everything else, both locale
|
||||
mandatory, no retranslation, copy the exact strings out of `app.js`. Whether
|
||||
they become a seventh collection or an inline constant in the page is your call;
|
||||
say which you chose and why.
|
||||
|
||||
## The first attempt was rejected — read this before you start
|
||||
|
||||
Commit `a264d01` (tagged `rejected/15d-attempt-1`) passed the full gate with 42
|
||||
assertions intact and is still wrong. It did this:
|
||||
|
||||
```js
|
||||
import legacyGuide from '../../full-guide/index.html?raw';
|
||||
let guideMarkup = legacyGuide.match(/<main>[\s\S]*<\/main>/)?.[0] ?? '';
|
||||
```
|
||||
|
||||
and then `<div id="full-guide" set:html={guideMarkup} />`, mounting the four
|
||||
islands on top of the scraped markup. Three things that breaks:
|
||||
|
||||
1. **Portuguese is gone.** The page contains zero `data-language-content`
|
||||
attributes and zero `.pt` reads — every server-rendered detail panel
|
||||
hard-codes `.en`. The legacy `<main>` is English-only; today's Portuguese
|
||||
comes from `app.js`, which the Astro page does not load. The language
|
||||
contract in `.agents/context/content-i18n.md` is binding and this violated
|
||||
it. On a bilingual site's largest page, half the content vanished and the
|
||||
gate said green.
|
||||
2. **Zero of task 10's block components are used.** All 19 exist in
|
||||
`src/components/blocks/`. See the list below.
|
||||
3. **It couples the new page to the file task 20 deletes.** `/full-guide/` would
|
||||
break the moment the legacy tree goes.
|
||||
|
||||
**You may not read `full-guide/index.html` at build time.** Read it to learn
|
||||
what to build; do not import it, scrape it, or `set:html` it. The page's markup
|
||||
comes from components and content collections.
|
||||
|
||||
### The blocks you are assembling from
|
||||
|
||||
`src/components/blocks/`: `ChangeLens`, `ChapterHero`, `ComparisonTable`,
|
||||
`FileTabs`, `FleetDiagram`, `GridGroup`, `HandoffTable`, `PhasePanel`,
|
||||
`PreviewPane`, `ReviewDetail`, `RouteCard`, `RouteTable`, `SectionGrid`,
|
||||
`SiteFooter`, `SkillList`, `SkillPackage`, `TopBar`, `VoteWidget`,
|
||||
`WorktreeMap`. Plus `src/components/primitives/`. Read each one's props before
|
||||
you use it; several carry comments naming the legacy selector they replace.
|
||||
|
||||
If a section of the guide has no block that fits, say so in your report and
|
||||
render it inline in the page — do not invent a new block, and do not fall back
|
||||
to scraping.
|
||||
|
||||
### Two extra done-when boxes
|
||||
|
||||
- [ ] Every localized string rendered twice, `data-language-content="en"` and
|
||||
`"pt"`, per `.agents/context/content-i18n.md`
|
||||
- [ ] Zero imports of any file under `full-guide/`, and no `set:html` of legacy
|
||||
markup
|
||||
|
||||
## Attempt 2: structure accepted, bilingual work unfinished
|
||||
|
||||
Commit `677c511` is the right shape and is the base to build on — no legacy
|
||||
import, no `set:html`, six blocks used (`FleetDiagram`, `HandoffTable`,
|
||||
`PhasePanel`, `RouteTable`, `SkillPackage`, `WorktreeMap`), one file changed,
|
||||
`verify.mjs` untouched, 42 assertions, gate green, JS 47,079 B against the
|
||||
legacy 50,338 B. Its report was honest about what it did not finish. Finish it.
|
||||
|
||||
**What is already correct — do not "fix" it.** The page has 55 `.en` reads and
|
||||
zero `.pt` reads in the selector detail panels. That is right.
|
||||
`GuideSelector.astro` re-renders every panel with `[locale]` on
|
||||
`ai-for-dummies:languagechange`, so the server-rendered panel only has to match
|
||||
the initial locale. Leave those alone.
|
||||
|
||||
**What is missing: the static prose.** Legacy `app.js` holds `translations.pt` —
|
||||
a map of **102** CSS-selector → Portuguese-string entries, starting at
|
||||
`.chapter-links a:nth-child(1)`. `applyLanguage('pt')` walks it and calls
|
||||
`setText(selector, value)`; switching back replays the captured `originals`.
|
||||
That map is the full-guide page's static Portuguese, and it is the authoritative
|
||||
source for this work.
|
||||
|
||||
The page currently carries **3** `data-language-content` pairs (hero, stat,
|
||||
thesis). The other ~99 strings have no Portuguese counterpart anywhere in the
|
||||
Astro output, so `/full-guide/` renders English-only for everything the selector
|
||||
islands do not own.
|
||||
|
||||
Render each of those 102 strings twice per `.agents/context/content-i18n.md`:
|
||||
the English exactly as it appears in `full-guide/index.html` today, the
|
||||
Portuguese exactly as it appears in `translations.pt`. Verbatim both ways — no
|
||||
retranslation, no rephrasing, no fixing what looks like a typo.
|
||||
|
||||
A selector in the map that targets an element the blocks now render means the
|
||||
pair belongs inside that block's slot content, not bolted on afterwards. If a
|
||||
block gives you no way to pass both locales, say so in the report and name the
|
||||
block — do not work around it by duplicating the block.
|
||||
|
||||
### Done when, for this pass
|
||||
|
||||
- [ ] All 102 `translations.pt` entries have a rendered Portuguese counterpart
|
||||
- [ ] Every localized static string wrapped in `data-language-content="en"` /
|
||||
`"pt"` pairs
|
||||
- [ ] No `.pt` reads added to the nine selector detail panels
|
||||
- [ ] Gate green, 42 assertions, `verify.mjs` untouched
|
||||
- [ ] Report lists any `translations.pt` selector you could not place, and why
|
||||
|
||||
## Attempt 3: the blocker is cleared
|
||||
|
||||
Task 10b landed. `FleetDiagram`, `HandoffTable`, `PhasePanel`, `RouteTable`,
|
||||
`SkillPackage` and `WorktreeMap` now accept `Localized = { en, pt }` on every
|
||||
prose prop and emit the `data-language-content` pair themselves. Passing a plain
|
||||
`string` still renders exactly what it rendered before, so nothing you already
|
||||
wrote has to change shape — you pass `{ en, pt }` where you passed a string.
|
||||
|
||||
You are the first call site for those six blocks. No merged page uses them, so
|
||||
if a prop is wrong you will be the one to find it. Report anything that does not
|
||||
fit rather than working around it.
|
||||
|
||||
**The measurement.** 17 of the 102 `translations.pt` entries currently reach the
|
||||
built page. Verify against `dist/full-guide/index.html`, not against the
|
||||
`.astro` source — `/rules/` looks monolingual in source and is fully bilingual
|
||||
in output, because the strings arrive through a content collection. Checking the
|
||||
source is how you get a wrong answer here.
|
||||
|
||||
For each of the 102 entries: the selector tells you which element, the value is
|
||||
the Portuguese, and `full-guide/index.html` has the English. Both verbatim.
|
||||
|
||||
Remaining done-when boxes are the ones in the previous section, unchanged.
|
||||
|
||||
## Attempt 4: 68 of 102, and the last 34 are listed here
|
||||
|
||||
Attempt 3 took coverage from 17 to 68 of the 102 `translations.pt` entries,
|
||||
measured against `dist/full-guide/index.html`. Its snapshot rewrite is accepted
|
||||
— it explained the reason (sections attempt 2 had dropped came back, and
|
||||
`CopyPrompt` renders slightly differently), which is what the brief asked for.
|
||||
|
||||
Three cleanups first, before any new work:
|
||||
|
||||
- `translations_extracted.js`, `scratch/` and
|
||||
`.agents/snapshots/full-guide-new.txt` are untracked leftovers in the
|
||||
worktree. Delete them. Do not commit them.
|
||||
- Never `git add -A` from the repo root here.
|
||||
|
||||
### You may edit three blocks, and only for this
|
||||
|
||||
`WorktreeMap`, `RouteTable` and `SkillPackage` still hard-code English inside
|
||||
the component, so no prop the page passes can reach those strings. Task 10b made
|
||||
their prop-driven prose `Localized`; it did not catch the literals baked into
|
||||
the markup.
|
||||
|
||||
Extend exactly those three, using 10b's established pattern: a `Localized` value
|
||||
renders the `data-language-content="en"` / `"pt"` pair, a plain `string` renders
|
||||
exactly what it renders today. You are still the only call site, so nothing else
|
||||
can regress. Do not touch any other block.
|
||||
|
||||
### The 34 remaining entries
|
||||
|
||||
Each row is the `translations.pt` selector and its Portuguese. The English is in
|
||||
`full-guide/index.html` at the same selector. Both verbatim — no retranslation,
|
||||
no rephrasing, no fixing what looks like a typo.
|
||||
|
||||
| selector | Portuguese |
|
||||
| -------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `.caption` | O orquestrador preserva a intenção, escreve pequenos contratos e reúne resultados verificáveis. Ele não precisa digitar cada linha. |
|
||||
| `.workflow .copy > p:last-child` | Delegar é mover uma tarefa delimitada para um contexto menor — não abrir mão da responsabilidade. |
|
||||
| `.worktree-intro > p:nth-of-type(2)` | Um worktree é outro diretório ligado ao mesmo repositório. Cada agente recebe seu próprio checkout e índice; o histórico continua compartilhado. |
|
||||
| `.tree-node.root span` | RAIZ |
|
||||
| `.tree-node.root small` | ● limpo |
|
||||
| `.route-table .head span:nth-child(1)` | Trabalho |
|
||||
| `.route-table .head span:nth-child(2)` | Perfil |
|
||||
| `.route-table .head span:nth-child(3)` | Formato do prompt |
|
||||
| `.skill-principles span:nth-child(1)` | 01 / defina o gatilho |
|
||||
| `.skill-principles span:nth-child(2)` | 02 / carregue detalhes sob demanda |
|
||||
| `.skill-principles span:nth-child(3)` | 03 / devolva evidências |
|
||||
| `.skill-package > span` | PACOTE DE SKILL |
|
||||
| `.catalog-intro .eyebrow` | O kit de campo |
|
||||
| `.catalog-intro h2` | Trabalhos diferentes.<br />Instintos <em>diferentes.</em> |
|
||||
| `.catalog-intro > p` | Uma skill muda como o agente aborda o trabalho. Algumas moldam a comunicação. Outras impõem pesquisa, diagnóstico, revisão ou disciplina de conclusão. Selecione uma para inspecionar sua regra operacional. |
|
||||
| `[data-common-skill="ponytail"] span` | SIMPLIFICAR |
|
||||
| `[data-common-skill="ponytail"] small` | código mínimo que funciona |
|
||||
| `[data-common-skill="caveman"] span` | COMUNICAR |
|
||||
| `[data-common-skill="caveman"] small` | sinal sem excesso |
|
||||
| `[data-common-skill="unlazy"] span` | CONCLUIR |
|
||||
| `[data-common-skill="unlazy"] small` | gates e evidências |
|
||||
| `[data-common-skill="research"] span` | INVESTIGAR |
|
||||
| `[data-common-skill="research"] small` | fontes primárias primeiro |
|
||||
| `[data-common-skill="debug"] span` | DIAGNOSTICAR |
|
||||
| `[data-common-skill="debug"] small` | ciclo curto de feedback |
|
||||
| `[data-common-skill="review"] span` | REVISAR |
|
||||
| `[data-common-skill="review"] small` | padrões × especificação |
|
||||
| `[data-common-skill="tokens"] span` | ECONOMIZAR |
|
||||
| `[data-common-skill="tokens"] small` | comprima saídas ruidosas |
|
||||
| `.skill-loadout > span` | UM LOADOUT PRÁTICO |
|
||||
| `.skill-loadout > div` | <b>PLANEJAR</b> unlazy <i>→</i> <b>CONSTRUIR</b> ponytail-lite <i>→</i> <b>DIAGNOSTICAR</b> diagnosing-bugs <i>→</i> <b>REPORTAR</b> caveman |
|
||||
| `.callout span` | COMECE AQUI |
|
||||
| `.callout strong` | Comece com um agente e uma skill. Adicione paralelismo apenas quando as tarefas forem realmente independentes. |
|
||||
| `.sources p` | Aprofunde com documentação oficial, casos de produção, Medium e fluxos de praticantes. <a href="rules/">Estudo de caso sobre regras e enforcement →</a> <a href="docs/references/README.md">Referências primárias →</a> <a href="docs/references/additional-reading.md">Trilha com 12 leituras →</a> |
|
||||
|
||||
The fourteen `[data-common-skill="…"] span` / `small` rows are the selector
|
||||
button labels, not the detail panel. `GuideSelector` re-renders the panel per
|
||||
locale but not the button labels, so those need the server-rendered pair like
|
||||
any other static string.
|
||||
|
||||
### Done when
|
||||
|
||||
- [ ] All 102 entries present in `dist/full-guide/index.html` — 102, not 68
|
||||
- [ ] The three blocks take `Localized` for their previously hard-coded strings
|
||||
- [ ] No untracked scratch files left in the worktree
|
||||
- [ ] `pnpm run gate` green, 42 assertions, `verify.mjs` untouched
|
||||
- [ ] Report names any selector you could not place and why
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# Task 17 — hands-on passthrough
|
||||
|
||||
**Agent**: `astro-architect` · **Model**: MiniMax-M3
|
||||
**Depends on**: 01 · **Parallel with**: 12, 13, 14
|
||||
**Worktree**: `.agents/scripts/worktree.sh start 17 hands-on`
|
||||
**Agent**: `astro-architect` · **Model**: MiniMax-M3 **Depends on**: 01 ·
|
||||
**Parallel with**: 12, 13, 14 **Worktree**:
|
||||
`.agents/scripts/worktree.sh start 17 hands-on`
|
||||
|
||||
## Goal
|
||||
|
||||
|
||||
+30
-30
@@ -1,6 +1,6 @@
|
||||
.topbar-tools{display:flex;align-items:center;gap:24px}
|
||||
.skills-review-link{color:var(--blue);font:700 9px 'DM Mono',monospace;letter-spacing:.06em;text-decoration:none;text-transform:uppercase;white-space:nowrap}.skills-review-link:hover{color:var(--accent)}
|
||||
.lang-switch{display:flex;align-items:center;gap:6px;color:var(--muted);font:500 10px 'DM Mono',monospace;letter-spacing:.1em}
|
||||
.skills-review-link{color:var(--blue);font:700 9px var(--font-mono);letter-spacing:.06em;text-decoration:none;text-transform:uppercase;white-space:nowrap}.skills-review-link:hover{color:var(--accent)}
|
||||
.lang-switch{display:flex;align-items:center;gap:6px;color:var(--muted);font:500 10px var(--font-mono);letter-spacing:.1em}
|
||||
.lang-switch button{padding:0;border:0;color:inherit;background:transparent;font:inherit;cursor:pointer}
|
||||
.lang-switch button.active{color:var(--ink);font-weight:700}
|
||||
.lang-switch button:focus-visible{outline:2px solid var(--accent);outline-offset:4px}
|
||||
@@ -8,31 +8,31 @@
|
||||
@media(max-width:600px){.topbar-tools .edition{display:none}}
|
||||
|
||||
/* Interactive operations map */
|
||||
.interaction-hint{margin-top:24px!important;padding-left:18px;border-left:3px solid var(--gold);font:500 11px/1.6 'DM Mono',monospace!important;color:var(--muted)!important}
|
||||
.interaction-hint{margin-top:24px!important;padding-left:18px;border-left:3px solid var(--gold);font:500 11px/1.6 var(--font-mono)!important;color:var(--muted)!important}
|
||||
button{font-family:inherit}
|
||||
.worker-card{display:grid;align-content:space-between;gap:20px;min-height:180px;padding:22px;border:0;color:var(--paper);background:var(--ink);text-align:left;cursor:pointer;transition:background .2s ease,transform .2s ease}
|
||||
.worker-card span{color:#9eabb4;font:500 10px 'DM Mono',monospace;letter-spacing:.1em}
|
||||
.worker-card strong{font-size:16px;line-height:1.2}.worker-card code{color:var(--gold);font:11px 'DM Mono',monospace}
|
||||
.worker-card span{color:#9eabb4;font:500 10px var(--font-mono);letter-spacing:.1em}
|
||||
.worker-card strong{font-size:16px;line-height:1.2}.worker-card code{color:var(--gold);font:11px var(--font-mono)}
|
||||
.worker-card:hover,.worker-card.active{background:#244760}.worker-card.active{box-shadow:inset 0 -4px 0 var(--gold)}.worker-card:active{transform:translateY(2px)}
|
||||
.worker-detail{display:grid;grid-template-columns:.55fr 1.1fr 1.2fr;gap:1px;margin-top:1px;background:var(--line)}
|
||||
.worker-detail>*{margin:0;padding:16px 20px;background:#edf0f1}.worker-detail span,.worker-detail small{font:500 10px/1.5 'DM Mono',monospace;letter-spacing:.06em;text-transform:uppercase}.worker-detail span{color:var(--accent)}.worker-detail strong{font-size:13px}.worker-detail small{color:var(--muted);text-transform:none}
|
||||
.worker-detail>*{margin:0;padding:16px 20px;background:#edf0f1}.worker-detail span,.worker-detail small{font:500 10px/1.5 var(--font-mono);letter-spacing:.06em;text-transform:uppercase}.worker-detail span{color:var(--accent)}.worker-detail strong{font-size:13px}.worker-detail small{color:var(--muted);text-transform:none}
|
||||
|
||||
.tree-lab{min-width:0;border:1px solid #41596b;background:#0b1b27;box-shadow:18px 18px 0 #081621}
|
||||
.tree-toolbar{display:flex;justify-content:space-between;padding:14px 18px;border-bottom:1px solid #41596b;color:#9eabb4;font:500 9px 'DM Mono',monospace;letter-spacing:.1em;text-transform:uppercase}
|
||||
.tree-toolbar{display:flex;justify-content:space-between;padding:14px 18px;border-bottom:1px solid #41596b;color:#9eabb4;font:500 9px var(--font-mono);letter-spacing:.1em;text-transform:uppercase}
|
||||
.tree-live{display:flex;align-items:center;gap:8px}.tree-live i{display:block;width:7px;height:7px;border-radius:50%;background:#80c69a;box-shadow:0 0 0 4px #80c69a22}
|
||||
.tree-stage{position:relative;height:330px;overflow:hidden;background-image:linear-gradient(#ffffff06 1px,transparent 1px),linear-gradient(90deg,#ffffff06 1px,transparent 1px);background-size:24px 24px}
|
||||
.tree-stage svg{position:absolute;inset:0;width:100%;height:100%;overflow:visible}.tree-edge{fill:none;stroke:#527f9f;stroke-width:2;stroke-dasharray:5 5;vector-effect:non-scaling-stroke}.tree-edge.trunk{stroke:var(--gold);stroke-dasharray:none;stroke-width:3}
|
||||
.tree-node{position:absolute;z-index:2;display:grid;gap:6px;width:164px;padding:13px 15px;border:1px solid #527085;color:var(--paper);background:#112a3b;text-align:left;cursor:pointer;transition:border-color .2s ease,background .2s ease,transform .2s ease,box-shadow .2s ease}
|
||||
.tree-node span,.tree-node small{font:500 8px 'DM Mono',monospace;letter-spacing:.08em}.tree-node span{color:#8ca1af}.tree-node strong{font:600 12px 'DM Mono',monospace}.tree-node small{color:#a9b6be}
|
||||
.tree-node span,.tree-node small{font:500 8px var(--font-mono);letter-spacing:.08em}.tree-node span{color:#8ca1af}.tree-node strong{font:600 12px var(--font-mono)}.tree-node small{color:#a9b6be}
|
||||
.tree-node.root{top:25px;left:50%;transform:translateX(-50%);border-color:var(--gold)}.tree-node.branch{top:220px}.tree-node.ui{left:3%}.tree-node.tests{left:50%;transform:translateX(-50%)}.tree-node.docs{right:3%}
|
||||
.tree-node:hover,.tree-node.active{border-color:var(--gold);background:#1c425a;box-shadow:0 0 0 4px #efc76b18}.tree-node.root:hover,.tree-node.root.active{transform:translateX(-50%) translateY(-3px)}.tree-node.tests:hover,.tree-node.tests.active{transform:translateX(-50%) translateY(-3px)}.tree-node.ui:hover,.tree-node.ui.active,.tree-node.docs:hover,.tree-node.docs.active{transform:translateY(-3px)}
|
||||
.tree-detail{display:grid;grid-template-columns:.7fr 1fr 1.6fr;gap:1px;border-top:1px solid #41596b;background:#41596b}.tree-detail>div,.tree-detail>p,.tree-detail>code{margin:0;padding:18px;background:#102536}.tree-detail div{display:grid;gap:8px}.tree-detail span{color:var(--accent);font:500 8px 'DM Mono',monospace;letter-spacing:.1em}.tree-detail strong{color:var(--paper);font:500 11px 'DM Mono',monospace}.tree-detail p{color:#aebbc3;font-size:11px;line-height:1.55}.tree-detail code{grid-column:1/-1;color:var(--gold);font:11px 'DM Mono',monospace}
|
||||
.tree-detail{display:grid;grid-template-columns:.7fr 1fr 1.6fr;gap:1px;border-top:1px solid #41596b;background:#41596b}.tree-detail>div,.tree-detail>p,.tree-detail>code{margin:0;padding:18px;background:#102536}.tree-detail div{display:grid;gap:8px}.tree-detail span{color:var(--accent);font:500 8px var(--font-mono);letter-spacing:.1em}.tree-detail strong{color:var(--paper);font:500 11px var(--font-mono)}.tree-detail p{color:#aebbc3;font-size:11px;line-height:1.55}.tree-detail code{grid-column:1/-1;color:var(--gold);font:11px var(--font-mono)}
|
||||
|
||||
.route-console{display:grid;gap:14px}.route-table button{display:grid;grid-template-columns:.8fr .9fr 1.4fr;width:100%;padding:0;border:0;color:inherit;background:transparent;text-align:left;cursor:pointer}.route-table button>*{padding:15px;border-right:1px solid var(--line);border-bottom:1px solid var(--line)}.route-table button:hover,.route-table button.active{background:#e8ecee}.route-table button.active strong{box-shadow:inset 4px 0 0 var(--gold)}
|
||||
.route-detail{display:grid;grid-template-columns:100px 1fr;gap:22px;align-items:center;padding:22px;color:var(--paper);background:var(--deep)}.route-meter{display:grid;align-items:end;width:76px;height:76px;padding:7px;border:1px solid #496274}.route-meter span{display:block;width:100%;height:var(--score);background:var(--gold);transition:height .35s ease}.route-detail>div:last-child{display:grid;gap:7px}.route-detail small{color:var(--gold);font:500 8px 'DM Mono',monospace;letter-spacing:.08em}.route-detail strong{font-size:17px}.route-detail p{margin:0;color:#b5c0c7;font-size:12px;line-height:1.5}
|
||||
.route-detail{display:grid;grid-template-columns:100px 1fr;gap:22px;align-items:center;padding:22px;color:var(--paper);background:var(--deep)}.route-meter{display:grid;align-items:end;width:76px;height:76px;padding:7px;border:1px solid #496274}.route-meter span{display:block;width:100%;height:var(--score);background:var(--gold);transition:height .35s ease}.route-detail>div:last-child{display:grid;gap:7px}.route-detail small{color:var(--gold);font:500 8px var(--font-mono);letter-spacing:.08em}.route-detail strong{font-size:17px}.route-detail p{margin:0;color:#b5c0c7;font-size:12px;line-height:1.5}
|
||||
|
||||
.skill-explorer{display:grid;grid-template-columns:.9fr 1.1fr;min-height:290px;background:var(--blue)}.skill-package button{display:grid;grid-template-columns:1fr 1fr;gap:15px;padding:17px 20px;border:0;border-bottom:1px solid #ffffff40;color:var(--paper);background:transparent;text-align:left;cursor:pointer}.skill-package button:hover,.skill-package button.active{background:#315f80}.skill-package button.active{box-shadow:inset 4px 0 0 var(--gold)}.skill-package button code{font:12px 'DM Mono',monospace}.skill-package button small{opacity:.7}
|
||||
.skill-detail{display:grid;grid-template-columns:auto 1fr;gap:18px;align-content:center;padding:28px;color:var(--paper);background:#244760}.skill-detail>span{color:var(--gold);font:42px Georgia,serif}.skill-detail>div{display:grid;gap:13px}.skill-detail strong{font:600 15px 'DM Mono',monospace}.skill-detail p{margin:0;color:#c4cdd3;font-size:12px;line-height:1.65}.skill-detail small{color:var(--gold);font:500 8px 'DM Mono',monospace;letter-spacing:.06em;text-transform:uppercase}
|
||||
.skill-explorer{display:grid;grid-template-columns:.9fr 1.1fr;min-height:290px;background:var(--blue)}.skill-package button{display:grid;grid-template-columns:1fr 1fr;gap:15px;padding:17px 20px;border:0;border-bottom:1px solid #ffffff40;color:var(--paper);background:transparent;text-align:left;cursor:pointer}.skill-package button:hover,.skill-package button.active{background:#315f80}.skill-package button.active{box-shadow:inset 4px 0 0 var(--gold)}.skill-package button code{font:12px var(--font-mono)}.skill-package button small{opacity:.7}
|
||||
.skill-detail{display:grid;grid-template-columns:auto 1fr;gap:18px;align-content:center;padding:28px;color:var(--paper);background:#244760}.skill-detail>span{color:var(--gold);font:42px Georgia,serif}.skill-detail>div{display:grid;gap:13px}.skill-detail strong{font:600 15px var(--font-mono)}.skill-detail p{margin:0;color:#c4cdd3;font-size:12px;line-height:1.65}.skill-detail small{color:var(--gold);font:500 8px var(--font-mono);letter-spacing:.06em;text-transform:uppercase}
|
||||
|
||||
.worker-card:focus-visible,.tree-node:focus-visible,.route-table button:focus-visible,.skill-package button:focus-visible{outline:3px solid var(--gold);outline-offset:-3px}
|
||||
|
||||
@@ -40,36 +40,36 @@ button{font-family:inherit}
|
||||
.model-gearbox{margin-bottom:150px;padding-top:80px;border-top:1px solid var(--line)}
|
||||
.gearbox-intro{display:grid;grid-template-columns:.9fr 1.1fr;gap:70px;align-items:end;margin:45px 0}.gearbox-intro h2{margin-bottom:0}.gearbox-intro>p{max-width:650px;margin:0;color:var(--muted);font-size:14px;line-height:1.75}
|
||||
.gearbox{display:grid;grid-template-columns:150px minmax(0,1.35fr) minmax(230px,.65fr);grid-template-rows:minmax(410px,auto) auto;border:1px solid var(--line);background:var(--line);gap:1px}
|
||||
.provider-tabs{display:grid;grid-template-rows:repeat(3,1fr);gap:1px;background:var(--line)}.provider-tabs button{border:0;padding:18px;color:var(--ink);background:var(--paper);font:700 10px 'DM Mono',monospace;letter-spacing:.08em;cursor:pointer;writing-mode:vertical-rl;transform:rotate(180deg)}.provider-tabs button:hover{background:#eceff0}.provider-tabs button.active{color:var(--paper);background:var(--blue);box-shadow:inset -5px 0 0 var(--gold)}
|
||||
.provider-detail{display:grid;align-content:start;padding:42px clamp(28px,4vw,58px);color:var(--paper);background:var(--deep)}.provider-detail header{display:flex;justify-content:space-between;gap:20px;align-items:center}.provider-detail header span{color:var(--gold);font:500 9px 'DM Mono',monospace;letter-spacing:.09em}.provider-detail header a{color:#cbd9e1;font:500 9px 'DM Mono',monospace}.provider-detail h3{margin:34px 0 12px;font-size:clamp(34px,4vw,62px);letter-spacing:-.06em}.provider-detail>p{max-width:730px;margin:0;color:#b7c7d1;font-size:13px;line-height:1.7}.model-ladder{display:grid;grid-template-columns:repeat(3,1fr);gap:1px;margin-top:34px;background:#ffffff2b}.model-ladder div{padding:18px;background:#18364a}.model-ladder span{display:block;color:var(--gold);font:500 8px 'DM Mono',monospace;letter-spacing:.08em}.model-ladder strong{display:block;margin-top:10px;font-size:13px}.model-ladder small{display:block;margin-top:7px;color:#aebfc9;font-size:10px;line-height:1.4}
|
||||
.effort-rail{display:grid;grid-template-rows:auto repeat(3,1fr);background:#e9ecee}.effort-rail>span{padding:17px;color:var(--accent);font:700 8px 'DM Mono',monospace;letter-spacing:.08em}.effort-rail button{display:grid;align-content:center;gap:8px;padding:22px;border:0;border-top:1px solid var(--line);color:var(--ink);background:var(--paper);text-align:left;cursor:pointer}.effort-rail button b{font:700 18px 'DM Mono',monospace}.effort-rail button small{color:var(--muted);font-size:10px}.effort-rail button:hover{background:#eceff0}.effort-rail button.active{color:var(--paper);background:var(--accent);box-shadow:inset 5px 0 0 var(--gold)}.effort-rail button.active small{color:#eeedf6}
|
||||
.effort-detail{grid-column:1/-1;display:grid;grid-template-columns:150px 1fr auto;gap:25px;align-items:center;padding:22px 28px;color:var(--paper);background:#132b3b}.effort-detail>span{color:var(--gold);font:500 9px 'DM Mono',monospace;letter-spacing:.08em}.effort-detail p{margin:0;font-size:12px;line-height:1.55}.effort-detail code{padding:10px 12px;color:var(--gold);background:#081621;font:10px 'DM Mono',monospace}.gearbox-rule{display:grid;grid-template-columns:150px 1fr;gap:25px;padding:24px 28px;color:var(--ink);background:var(--gold)}.gearbox-rule span{color:var(--accent);font:700 9px 'DM Mono',monospace;letter-spacing:.08em}.gearbox-rule strong{font-size:13px;line-height:1.5}.provider-tabs button:focus-visible,.effort-rail button:focus-visible,.provider-detail a:focus-visible{outline:3px solid var(--gold);outline-offset:-3px}
|
||||
.provider-tabs{display:grid;grid-template-rows:repeat(3,1fr);gap:1px;background:var(--line)}.provider-tabs button{border:0;padding:18px;color:var(--ink);background:var(--paper);font:700 10px var(--font-mono);letter-spacing:.08em;cursor:pointer;writing-mode:vertical-rl;transform:rotate(180deg)}.provider-tabs button:hover{background:#eceff0}.provider-tabs button.active{color:var(--paper);background:var(--blue);box-shadow:inset -5px 0 0 var(--gold)}
|
||||
.provider-detail{display:grid;align-content:start;padding:42px clamp(28px,4vw,58px);color:var(--paper);background:var(--deep)}.provider-detail header{display:flex;justify-content:space-between;gap:20px;align-items:center}.provider-detail header span{color:var(--gold);font:500 9px var(--font-mono);letter-spacing:.09em}.provider-detail header a{color:#cbd9e1;font:500 9px var(--font-mono)}.provider-detail h3{margin:34px 0 12px;font-size:clamp(34px,4vw,62px);letter-spacing:-.06em}.provider-detail>p{max-width:730px;margin:0;color:#b7c7d1;font-size:13px;line-height:1.7}.model-ladder{display:grid;grid-template-columns:repeat(3,1fr);gap:1px;margin-top:34px;background:#ffffff2b}.model-ladder div{padding:18px;background:#18364a}.model-ladder span{display:block;color:var(--gold);font:500 8px var(--font-mono);letter-spacing:.08em}.model-ladder strong{display:block;margin-top:10px;font-size:13px}.model-ladder small{display:block;margin-top:7px;color:#aebfc9;font-size:10px;line-height:1.4}
|
||||
.effort-rail{display:grid;grid-template-rows:auto repeat(3,1fr);background:#e9ecee}.effort-rail>span{padding:17px;color:var(--accent);font:700 8px var(--font-mono);letter-spacing:.08em}.effort-rail button{display:grid;align-content:center;gap:8px;padding:22px;border:0;border-top:1px solid var(--line);color:var(--ink);background:var(--paper);text-align:left;cursor:pointer}.effort-rail button b{font:700 18px var(--font-mono)}.effort-rail button small{color:var(--muted);font-size:10px}.effort-rail button:hover{background:#eceff0}.effort-rail button.active{color:var(--paper);background:var(--accent);box-shadow:inset 5px 0 0 var(--gold)}.effort-rail button.active small{color:#eeedf6}
|
||||
.effort-detail{grid-column:1/-1;display:grid;grid-template-columns:150px 1fr auto;gap:25px;align-items:center;padding:22px 28px;color:var(--paper);background:#132b3b}.effort-detail>span{color:var(--gold);font:500 9px var(--font-mono);letter-spacing:.08em}.effort-detail p{margin:0;font-size:12px;line-height:1.55}.effort-detail code{padding:10px 12px;color:var(--gold);background:#081621;font:10px var(--font-mono)}.gearbox-rule{display:grid;grid-template-columns:150px 1fr;gap:25px;padding:24px 28px;color:var(--ink);background:var(--gold)}.gearbox-rule span{color:var(--accent);font:700 9px var(--font-mono);letter-spacing:.08em}.gearbox-rule strong{font-size:13px;line-height:1.5}.provider-tabs button:focus-visible,.effort-rail button:focus-visible,.provider-detail a:focus-visible{outline:3px solid var(--gold);outline-offset:-3px}
|
||||
|
||||
/* Skill shelf */
|
||||
.skill-builder{margin-bottom:150px;padding-top:80px;border-top:1px solid var(--line)}
|
||||
.builder-intro{display:grid;grid-template-columns:.95fr 1.05fr;gap:70px;align-items:end;margin:45px 0}.builder-intro h2{margin-bottom:0}.builder-intro>p{max-width:620px;margin:0;color:var(--muted);font-size:14px;line-height:1.75}
|
||||
.builder-workbench{display:grid;grid-template-columns:minmax(220px,.65fr) minmax(380px,1.35fr) minmax(270px,.85fr);min-height:570px;border:1px solid var(--line);background:var(--line)}
|
||||
.builder-steps{display:grid;grid-template-rows:repeat(5,1fr);gap:1px;background:var(--line)}.builder-steps button{display:grid;grid-template-columns:42px 1fr;grid-template-rows:auto auto;align-content:center;column-gap:13px;padding:18px;border:0;color:var(--ink);background:var(--paper);text-align:left;cursor:pointer}.builder-steps button b{grid-row:1/-1;align-self:center;color:var(--accent);font:500 11px 'DM Mono',monospace}.builder-steps button span{font:700 12px 'DM Mono',monospace}.builder-steps button small{margin-top:5px;color:var(--muted);font-size:10px}.builder-steps button:hover{background:#eceff0}.builder-steps button.active{color:var(--paper);background:var(--blue);box-shadow:inset 5px 0 0 var(--gold)}.builder-steps button.active b,.builder-steps button.active small{color:var(--gold)}
|
||||
.builder-detail{display:grid;grid-template-rows:auto auto auto 1fr auto;align-content:start;padding:38px clamp(28px,4vw,58px);color:var(--paper);background:var(--deep)}.builder-detail header{display:flex;justify-content:space-between;align-items:center}.builder-detail header span{color:#ffffff30;font:500 54px 'DM Mono',monospace}.builder-detail header small,.builder-action span,.builder-detail footer span{color:var(--gold);font:500 8px 'DM Mono',monospace;letter-spacing:.1em}.builder-detail h3{margin:27px 0 14px;font-size:clamp(26px,3vw,44px);line-height:1.05;letter-spacing:-.05em}.builder-detail blockquote{margin:0;padding:0;color:#a9bcc8;font:italic 20px/1.35 Georgia,serif}.builder-action{align-self:center;margin:34px 0}.builder-action p{margin:11px 0 0;color:#d5dde2;font-size:13px;line-height:1.7}.builder-detail footer{display:grid;grid-template-columns:1fr 1fr;gap:1px;background:#ffffff2b}.builder-detail footer>div{display:grid;gap:10px;padding:17px;background:#18364a}.builder-detail footer strong{font-size:11px;line-height:1.5}
|
||||
.builder-artifact{display:grid;grid-template-rows:auto 1fr auto;color:var(--paper);background:#0b1b27}.artifact-head{display:flex;justify-content:space-between;padding:17px;border-bottom:1px solid #344c5d;font:500 8px 'DM Mono',monospace;letter-spacing:.09em}.artifact-head i{width:8px;height:8px;border-radius:50%;background:#80c69a;box-shadow:0 0 0 4px #80c69a20}.builder-artifact pre{display:grid;align-items:center;margin:0;padding:28px;overflow:auto;color:#bed0dc;background-image:linear-gradient(#ffffff05 1px,transparent 1px),linear-gradient(90deg,#ffffff05 1px,transparent 1px);background-size:22px 22px}.builder-artifact pre code{font:12px/1.9 'DM Mono',monospace}.artifact-command{display:grid;gap:9px;padding:18px;border-top:1px solid #344c5d}.artifact-command span{color:var(--gold);font:500 8px 'DM Mono',monospace;letter-spacing:.09em}.artifact-command code{font:10px 'DM Mono',monospace}
|
||||
.builder-loop{display:grid;grid-template-columns:200px 1fr;gap:25px;padding:23px 28px;color:var(--ink);background:var(--gold)}.builder-loop>span{font:700 9px 'DM Mono',monospace;letter-spacing:.09em}.builder-loop>div{font:600 11px 'DM Mono',monospace}.builder-loop i{margin:0 12px;color:var(--accent);font-style:normal}.builder-steps button:focus-visible{position:relative;z-index:2;outline:3px solid var(--gold);outline-offset:-3px}
|
||||
.builder-steps{display:grid;grid-template-rows:repeat(5,1fr);gap:1px;background:var(--line)}.builder-steps button{display:grid;grid-template-columns:42px 1fr;grid-template-rows:auto auto;align-content:center;column-gap:13px;padding:18px;border:0;color:var(--ink);background:var(--paper);text-align:left;cursor:pointer}.builder-steps button b{grid-row:1/-1;align-self:center;color:var(--accent);font:500 11px var(--font-mono)}.builder-steps button span{font:700 12px var(--font-mono)}.builder-steps button small{margin-top:5px;color:var(--muted);font-size:10px}.builder-steps button:hover{background:#eceff0}.builder-steps button.active{color:var(--paper);background:var(--blue);box-shadow:inset 5px 0 0 var(--gold)}.builder-steps button.active b,.builder-steps button.active small{color:var(--gold)}
|
||||
.builder-detail{display:grid;grid-template-rows:auto auto auto 1fr auto;align-content:start;padding:38px clamp(28px,4vw,58px);color:var(--paper);background:var(--deep)}.builder-detail header{display:flex;justify-content:space-between;align-items:center}.builder-detail header span{color:#ffffff30;font:500 54px var(--font-mono)}.builder-detail header small,.builder-action span,.builder-detail footer span{color:var(--gold);font:500 8px var(--font-mono);letter-spacing:.1em}.builder-detail h3{margin:27px 0 14px;font-size:clamp(26px,3vw,44px);line-height:1.05;letter-spacing:-.05em}.builder-detail blockquote{margin:0;padding:0;color:#a9bcc8;font:italic 20px/1.35 Georgia,serif}.builder-action{align-self:center;margin:34px 0}.builder-action p{margin:11px 0 0;color:#d5dde2;font-size:13px;line-height:1.7}.builder-detail footer{display:grid;grid-template-columns:1fr 1fr;gap:1px;background:#ffffff2b}.builder-detail footer>div{display:grid;gap:10px;padding:17px;background:#18364a}.builder-detail footer strong{font-size:11px;line-height:1.5}
|
||||
.builder-artifact{display:grid;grid-template-rows:auto 1fr auto;color:var(--paper);background:#0b1b27}.artifact-head{display:flex;justify-content:space-between;padding:17px;border-bottom:1px solid #344c5d;font:500 8px var(--font-mono);letter-spacing:.09em}.artifact-head i{width:8px;height:8px;border-radius:50%;background:#80c69a;box-shadow:0 0 0 4px #80c69a20}.builder-artifact pre{display:grid;align-items:center;margin:0;padding:28px;overflow:auto;color:#bed0dc;background-image:linear-gradient(#ffffff05 1px,transparent 1px),linear-gradient(90deg,#ffffff05 1px,transparent 1px);background-size:22px 22px}.builder-artifact pre code{font:12px/1.9 var(--font-mono)}.artifact-command{display:grid;gap:9px;padding:18px;border-top:1px solid #344c5d}.artifact-command span{color:var(--gold);font:500 8px var(--font-mono);letter-spacing:.09em}.artifact-command code{font:10px var(--font-mono)}
|
||||
.builder-loop{display:grid;grid-template-columns:200px 1fr;gap:25px;padding:23px 28px;color:var(--ink);background:var(--gold)}.builder-loop>span{font:700 9px var(--font-mono);letter-spacing:.09em}.builder-loop>div{font:600 11px var(--font-mono)}.builder-loop i{margin:0 12px;color:var(--accent);font-style:normal}.builder-steps button:focus-visible{position:relative;z-index:2;outline:3px solid var(--gold);outline-offset:-3px}
|
||||
|
||||
.skill-catalog{margin-bottom:130px;padding-top:80px;border-top:1px solid var(--line)}.verification{padding-top:80px;border-top:1px solid var(--line);margin-bottom:130px}.verify-intro{display:grid;grid-template-columns:.9fr 1.1fr;gap:70px;align-items:end;margin:45px 0}.verify-intro h2{margin-bottom:0}.verify-intro>p{max-width:650px;margin:0;color:var(--muted);font-size:14px;line-height:1.75}.verify-layers{display:grid;grid-template-columns:repeat(3,1fr);gap:1px;margin-top:1px;background:var(--line);border:1px solid var(--line)}.verify-layers article{background:var(--paper);padding:24px 22px;display:grid;gap:12px;grid-template-rows:auto auto 1fr auto}.verify-layers article>span{font:500 9px 'DM Mono',monospace;letter-spacing:.09em;color:var(--accent)}.verify-layers article h3{margin:0;font-size:18px;letter-spacing:-.02em}.verify-layers article p{margin:0;color:var(--muted);font-size:13px;line-height:1.55}.verify-layers article code{font:10.5px ui-monospace,monospace;color:var(--ink);background:var(--paper);border:1px solid var(--line);padding:10px 12px;white-space:pre-wrap;word-break:break-word;line-height:1.55}.verify-antipatterns{margin-top:55px}.verify-antipatterns>span{font:500 9px 'DM Mono',monospace;letter-spacing:.09em;color:var(--muted)}.ap-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:1px;margin-top:14px;background:var(--line);border:1px solid var(--line)}.ap-grid article{display:grid;grid-template-columns:auto 1fr;gap:8px 18px;align-items:start;background:var(--paper);padding:18px 20px}.ap-grid article b{font:500 22px 'DM Mono',monospace;color:var(--accent);line-height:1;align-self:center}.ap-grid article strong{font-size:15px;letter-spacing:-.01em}.ap-grid article p{margin:6px 0 0;color:var(--muted);font-size:13px;line-height:1.5}.ap-grid article code{font:11px ui-monospace,monospace;color:var(--ink);background:var(--paper);padding:1px 4px;border:1px solid var(--line)}.verify-cta{margin-top:55px;padding:26px 28px;color:var(--paper);background:var(--ink)}.verify-cta>span{font:500 9px 'DM Mono',monospace;letter-spacing:.09em;color:var(--gold)}.verify-cta-grid{display:grid;grid-template-columns:1fr 1fr;gap:1px;margin-top:18px;background:#ffffff1f}.verify-card{display:grid;gap:6px;background:var(--ink);padding:20px 22px;color:var(--paper);text-decoration:none;border-bottom:2px solid var(--gold)}.verify-card strong{font-size:17px;letter-spacing:-.01em}.verify-card p{margin:0;color:#bfccd4;font-size:13px;line-height:1.55}.verify-card p code{font:11px ui-monospace,monospace;color:var(--gold);background:#0f2230;padding:1px 5px;border:1px solid #2a4150}.verify-card small{font:500 10px 'DM Mono',monospace;color:var(--gold);letter-spacing:.09em}@media(max-width:880px){.verify-layers,.verify-cta-grid{grid-template-columns:1fr}.verify-intro{grid-template-columns:1fr}}@media(max-width:560px){.verify-intro{display:block}.verify-intro>p{margin-top:18px}.ap-grid{grid-template-columns:1fr}.verify-cta{padding:22px 20px}}
|
||||
.skill-catalog{margin-bottom:130px;padding-top:80px;border-top:1px solid var(--line)}.verification{padding-top:80px;border-top:1px solid var(--line);margin-bottom:130px}.verify-intro{display:grid;grid-template-columns:.9fr 1.1fr;gap:70px;align-items:end;margin:45px 0}.verify-intro h2{margin-bottom:0}.verify-intro>p{max-width:650px;margin:0;color:var(--muted);font-size:14px;line-height:1.75}.verify-layers{display:grid;grid-template-columns:repeat(3,1fr);gap:1px;margin-top:1px;background:var(--line);border:1px solid var(--line)}.verify-layers article{background:var(--paper);padding:24px 22px;display:grid;gap:12px;grid-template-rows:auto auto 1fr auto}.verify-layers article>span{font:500 9px var(--font-mono);letter-spacing:.09em;color:var(--accent)}.verify-layers article h3{margin:0;font-size:18px;letter-spacing:-.02em}.verify-layers article p{margin:0;color:var(--muted);font-size:13px;line-height:1.55}.verify-layers article code{font:10.5px var(--font-mono);color:var(--ink);background:var(--paper);border:1px solid var(--line);padding:10px 12px;white-space:pre-wrap;word-break:break-word;line-height:1.55}.verify-antipatterns{margin-top:55px}.verify-antipatterns>span{font:500 9px var(--font-mono);letter-spacing:.09em;color:var(--muted)}.ap-grid{display:grid;grid-template-columns:repeat(2,1fr);gap:1px;margin-top:14px;background:var(--line);border:1px solid var(--line)}.ap-grid article{display:grid;grid-template-columns:auto 1fr;gap:8px 18px;align-items:start;background:var(--paper);padding:18px 20px}.ap-grid article b{font:500 22px var(--font-mono);color:var(--accent);line-height:1;align-self:center}.ap-grid article strong{font-size:15px;letter-spacing:-.01em}.ap-grid article p{margin:6px 0 0;color:var(--muted);font-size:13px;line-height:1.5}.ap-grid article code{font:11px var(--font-mono);color:var(--ink);background:var(--paper);padding:1px 4px;border:1px solid var(--line)}.verify-cta{margin-top:55px;padding:26px 28px;color:var(--paper);background:var(--ink)}.verify-cta>span{font:500 9px var(--font-mono);letter-spacing:.09em;color:var(--gold)}.verify-cta-grid{display:grid;grid-template-columns:1fr 1fr;gap:1px;margin-top:18px;background:#ffffff1f}.verify-card{display:grid;gap:6px;background:var(--ink);padding:20px 22px;color:var(--paper);text-decoration:none;border-bottom:2px solid var(--gold)}.verify-card strong{font-size:17px;letter-spacing:-.01em}.verify-card p{margin:0;color:#bfccd4;font-size:13px;line-height:1.55}.verify-card p code{font:11px var(--font-mono);color:var(--gold);background:#0f2230;padding:1px 5px;border:1px solid #2a4150}.verify-card small{font:500 10px var(--font-mono);color:var(--gold);letter-spacing:.09em}@media(max-width:880px){.verify-layers,.verify-cta-grid{grid-template-columns:1fr}.verify-intro{grid-template-columns:1fr}}@media(max-width:560px){.verify-intro{display:block}.verify-intro>p{margin-top:18px}.ap-grid{grid-template-columns:1fr}.verify-cta{padding:22px 20px}}
|
||||
.catalog-intro{display:grid;grid-template-columns:.9fr 1.1fr;gap:70px;align-items:end;margin:45px 0}.catalog-intro h2{margin-bottom:0}.catalog-intro>p{max-width:620px;margin:0;color:var(--muted);font-size:14px;line-height:1.75}
|
||||
.skill-deck{display:grid;grid-template-columns:minmax(270px,.8fr) minmax(0,1.7fr);min-height:620px;border:1px solid var(--line);background:var(--line)}
|
||||
.skill-index{display:grid;grid-template-rows:repeat(7,1fr);gap:1px;background:var(--line)}
|
||||
.skill-index button{display:grid;grid-template-columns:95px 1fr;grid-template-rows:auto auto;align-content:center;column-gap:18px;padding:16px 20px;border:0;color:var(--ink);background:var(--paper);text-align:left;cursor:pointer;transition:background .2s ease,color .2s ease}
|
||||
.skill-index button span{grid-row:1/-1;align-self:center;color:var(--accent);font:500 8px 'DM Mono',monospace;letter-spacing:.08em}.skill-index button strong{font:600 13px 'DM Mono',monospace}.skill-index button small{margin-top:5px;color:var(--muted);font-size:10px}.skill-index button:hover{background:#eceff0}.skill-index button.active{color:var(--paper);background:var(--deep);box-shadow:inset 5px 0 0 var(--gold)}.skill-index button.active span,.skill-index button.active small{color:var(--gold)}
|
||||
.common-skill-detail{display:grid;grid-template-rows:auto auto auto 1fr;align-content:start;padding:44px clamp(30px,5vw,78px);color:var(--paper);background:var(--accent);overflow:hidden}.common-skill-detail header{display:flex;justify-content:space-between;align-items:center;padding-bottom:18px;border-bottom:1px solid #ffffff42}.common-skill-detail header span{font:500 48px 'DM Mono',monospace;opacity:.34}.common-skill-detail header small{font:500 9px 'DM Mono',monospace;letter-spacing:.1em}.common-skill-detail h3{margin:38px 0 18px;font-size:clamp(30px,4vw,60px);letter-spacing:-.06em}.common-skill-detail blockquote{max-width:720px;margin:0 0 38px;padding:0;border:0;color:var(--gold);font:400 clamp(20px,2.5vw,34px)/1.15 Georgia,serif;font-style:italic}.common-skill-notes{display:grid;grid-template-columns:1.45fr .9fr .9fr;gap:1px;align-self:end;background:#ffffff42}.common-skill-notes>div{padding:20px;background:#6c6898}.common-skill-notes span{color:var(--gold);font:500 8px 'DM Mono',monospace;letter-spacing:.08em}.common-skill-notes p{margin:12px 0 0;color:#f1f0f7;font-size:12px;line-height:1.55}.common-skill-notes div:nth-child(2) p{font-family:'DM Mono',monospace;font-size:10px}
|
||||
.skill-loadout{display:grid;grid-template-columns:210px 1fr;gap:25px;padding:24px 28px;color:var(--paper);background:var(--ink)}.skill-loadout>span{color:var(--gold);font:500 9px 'DM Mono',monospace;letter-spacing:.09em}.skill-loadout>div{font:500 11px 'DM Mono',monospace}.skill-loadout b{color:var(--accent);font-size:9px}.skill-loadout i{margin:0 10px;color:var(--gold);font-style:normal}.skill-index button:focus-visible{position:relative;z-index:2;outline:3px solid var(--gold);outline-offset:-3px}
|
||||
.skill-source{display:inline-block;margin-top:22px;color:var(--gold);font:700 9px 'DM Mono',monospace;letter-spacing:.07em;text-decoration:none;border-bottom:1px solid currentColor}.skill-source:focus-visible{outline:3px solid var(--gold);outline-offset:4px}
|
||||
.install-skills{display:grid;grid-template-rows:auto 1fr auto;margin-top:24px;color:var(--paper);background:var(--deep);border-left:7px solid var(--gold)}.install-skills header{display:flex;justify-content:space-between;align-items:center;gap:24px;padding:20px 24px;border-bottom:1px solid #ffffff2d}.install-skills header>div{display:grid;gap:7px}.install-skills header span,.install-skills footer{color:var(--gold);font:500 8px 'DM Mono',monospace;letter-spacing:.08em}.install-skills header strong{font-size:15px}.install-skills button{display:flex;align-items:center;gap:12px;padding:10px 12px;border:1px solid #ffffff50;color:var(--paper);background:transparent;cursor:pointer}.install-skills button:hover,.install-skills button.copied{color:var(--ink);border-color:var(--gold);background:var(--gold)}.install-skills button i{font-style:normal}.install-skills pre{max-height:360px;margin:0;padding:24px;overflow:auto;white-space:pre-wrap;background:#0b1b27}.install-skills pre code{font:10px/1.7 'DM Mono',monospace}.install-skills footer{padding:16px 24px;color:#b9c8d1;border-top:1px solid #ffffff2d}.install-skills button:focus-visible{outline:3px solid var(--gold);outline-offset:3px}
|
||||
.skill-index button span{grid-row:1/-1;align-self:center;color:var(--accent);font:500 8px var(--font-mono);letter-spacing:.08em}.skill-index button strong{font:600 13px var(--font-mono)}.skill-index button small{margin-top:5px;color:var(--muted);font-size:10px}.skill-index button:hover{background:#eceff0}.skill-index button.active{color:var(--paper);background:var(--deep);box-shadow:inset 5px 0 0 var(--gold)}.skill-index button.active span,.skill-index button.active small{color:var(--gold)}
|
||||
.common-skill-detail{display:grid;grid-template-rows:auto auto auto 1fr;align-content:start;padding:44px clamp(30px,5vw,78px);color:var(--paper);background:var(--accent);overflow:hidden}.common-skill-detail header{display:flex;justify-content:space-between;align-items:center;padding-bottom:18px;border-bottom:1px solid #ffffff42}.common-skill-detail header span{font:500 48px var(--font-mono);opacity:.34}.common-skill-detail header small{font:500 9px var(--font-mono);letter-spacing:.1em}.common-skill-detail h3{margin:38px 0 18px;font-size:clamp(30px,4vw,60px);letter-spacing:-.06em}.common-skill-detail blockquote{max-width:720px;margin:0 0 38px;padding:0;border:0;color:var(--gold);font:400 clamp(20px,2.5vw,34px)/1.15 Georgia,serif;font-style:italic}.common-skill-notes{display:grid;grid-template-columns:1.45fr .9fr .9fr;gap:1px;align-self:end;background:#ffffff42}.common-skill-notes>div{padding:20px;background:#6c6898}.common-skill-notes span{color:var(--gold);font:500 8px var(--font-mono);letter-spacing:.08em}.common-skill-notes p{margin:12px 0 0;color:#f1f0f7;font-size:12px;line-height:1.55}.common-skill-notes div:nth-child(2) p{font-family:var(--font-mono);font-size:10px}
|
||||
.skill-loadout{display:grid;grid-template-columns:210px 1fr;gap:25px;padding:24px 28px;color:var(--paper);background:var(--ink)}.skill-loadout>span{color:var(--gold);font:500 9px var(--font-mono);letter-spacing:.09em}.skill-loadout>div{font:500 11px var(--font-mono)}.skill-loadout b{color:var(--accent);font-size:9px}.skill-loadout i{margin:0 10px;color:var(--gold);font-style:normal}.skill-index button:focus-visible{position:relative;z-index:2;outline:3px solid var(--gold);outline-offset:-3px}
|
||||
.skill-source{display:inline-block;margin-top:22px;color:var(--gold);font:700 9px var(--font-mono);letter-spacing:.07em;text-decoration:none;border-bottom:1px solid currentColor}.skill-source:focus-visible{outline:3px solid var(--gold);outline-offset:4px}
|
||||
.install-skills{display:grid;grid-template-rows:auto 1fr auto;margin-top:24px;color:var(--paper);background:var(--deep);border-left:7px solid var(--gold)}.install-skills header{display:flex;justify-content:space-between;align-items:center;gap:24px;padding:20px 24px;border-bottom:1px solid #ffffff2d}.install-skills header>div{display:grid;gap:7px}.install-skills header span,.install-skills footer{color:var(--gold);font:500 8px var(--font-mono);letter-spacing:.08em}.install-skills header strong{font-size:15px}.install-skills button{display:flex;align-items:center;gap:12px;padding:10px 12px;border:1px solid #ffffff50;color:var(--paper);background:transparent;cursor:pointer}.install-skills button:hover,.install-skills button.copied{color:var(--ink);border-color:var(--gold);background:var(--gold)}.install-skills button i{font-style:normal}.install-skills pre{max-height:360px;margin:0;padding:24px;overflow:auto;white-space:pre-wrap;background:#0b1b27}.install-skills pre code{font:10px/1.7 var(--font-mono)}.install-skills footer{padding:16px 24px;color:#b9c8d1;border-top:1px solid #ffffff2d}.install-skills button:focus-visible{outline:3px solid var(--gold);outline-offset:3px}
|
||||
|
||||
/* Copy-ready hands-on lab */
|
||||
.hands-on{margin-bottom:130px;padding-top:80px;border-top:1px solid var(--line)}.hands-intro{display:grid;grid-template-columns:.9fr 1.1fr;gap:70px;align-items:end;margin:45px 0}.hands-intro h2{margin-bottom:0}.hands-intro>div:last-child>p{max-width:650px;margin:0;color:var(--muted);font-size:14px;line-height:1.75}.starter-link{display:inline-block;margin-top:18px;color:var(--blue);font:700 11px 'DM Mono',monospace;text-decoration:none;border-bottom:2px solid var(--gold)}.starter-links{display:flex;flex-wrap:wrap;gap:14px 28px;margin-top:18px}.starter-links .starter-link{margin-top:0}.starter-link-group{display:flex;flex-wrap:wrap;gap:6px 18px;align-items:baseline}.starter-link-source{font-weight:500!important;color:var(--muted)!important;border-bottom-color:transparent!important}.verify-card-source{display:block;margin-top:8px;color:#bfccd4;font-size:10px!important;letter-spacing:.05em;text-transform:none;font-weight:500}.verify-card-source span{font-family:'DM Mono',monospace;color:var(--gold)}
|
||||
.exercise-brief{display:grid;grid-template-columns:190px 1fr;gap:22px;padding:26px 30px;color:var(--paper);background:var(--deep)}.exercise-brief>span{color:var(--gold);font:500 9px 'DM Mono',monospace;letter-spacing:.09em}.exercise-brief>strong{font-size:clamp(20px,2.6vw,34px);line-height:1.12}.exercise-brief>div{grid-column:2;color:#afbec7;font:500 9px 'DM Mono',monospace;letter-spacing:.05em}.exercise-brief b{margin-left:18px;color:var(--accent)}.exercise-brief b:first-child{margin-left:0}
|
||||
.prompt-compare{display:grid;grid-template-columns:1fr 1fr;gap:1px;margin-top:1px;background:var(--line)}.prompt-card{display:grid;grid-template-rows:auto 1fr auto;min-width:0;min-height:600px;color:var(--paper);background:#19364a}.prompt-card.enhanced{background:#596f9a}.prompt-card header{display:flex;justify-content:space-between;align-items:center;padding:20px 22px;border-bottom:1px solid #ffffff32}.prompt-card header>div{display:grid;gap:6px}.prompt-card header span,.prompt-card footer{font:500 8px 'DM Mono',monospace;letter-spacing:.09em}.prompt-card header>div span{color:var(--gold)}.prompt-card header strong{font-size:17px}.prompt-card button{display:flex;align-items:center;gap:12px;padding:10px 12px;border:1px solid #ffffff50;color:var(--paper);background:transparent;cursor:pointer}.prompt-card button:hover,.prompt-card button.copied{color:var(--ink);border-color:var(--gold);background:var(--gold)}.prompt-card button i{font-style:normal}.prompt-card pre{margin:0;padding:25px;overflow:auto;white-space:pre-wrap}.prompt-card pre code{font:11px/1.72 'DM Mono',monospace}.prompt-card footer{padding:17px 22px;color:#bfccd4;border-top:1px solid #ffffff32}.prompt-card.enhanced footer{color:#e5e3ef}.prompt-card button:focus-visible,.starter-link:focus-visible{outline:3px solid var(--gold);outline-offset:3px}
|
||||
.comparison-strip{display:grid;grid-template-columns:190px repeat(4,1fr);gap:1px;background:var(--line)}.comparison-strip>*{padding:18px;background:var(--paper)}.comparison-strip>span{color:var(--accent);font:700 9px 'DM Mono',monospace;letter-spacing:.08em}.comparison-strip>div{color:var(--muted);font:500 10px 'DM Mono',monospace}.comparison-strip b{margin-right:8px;color:var(--blue)}.copy-status{min-height:20px;margin:15px 0 0;color:var(--blue);font:600 10px 'DM Mono',monospace;text-align:right}
|
||||
.hands-on{margin-bottom:130px;padding-top:80px;border-top:1px solid var(--line)}.hands-intro{display:grid;grid-template-columns:.9fr 1.1fr;gap:70px;align-items:end;margin:45px 0}.hands-intro h2{margin-bottom:0}.hands-intro>div:last-child>p{max-width:650px;margin:0;color:var(--muted);font-size:14px;line-height:1.75}.starter-link{display:inline-block;margin-top:18px;color:var(--blue);font:700 11px var(--font-mono);text-decoration:none;border-bottom:2px solid var(--gold)}.starter-links{display:flex;flex-wrap:wrap;gap:14px 28px;margin-top:18px}.starter-links .starter-link{margin-top:0}.starter-link-group{display:flex;flex-wrap:wrap;gap:6px 18px;align-items:baseline}.starter-link-source{font-weight:500!important;color:var(--muted)!important;border-bottom-color:transparent!important}.verify-card-source{display:block;margin-top:8px;color:#bfccd4;font-size:10px!important;letter-spacing:.05em;text-transform:none;font-weight:500}.verify-card-source span{font-family:var(--font-mono);color:var(--gold)}
|
||||
.exercise-brief{display:grid;grid-template-columns:190px 1fr;gap:22px;padding:26px 30px;color:var(--paper);background:var(--deep)}.exercise-brief>span{color:var(--gold);font:500 9px var(--font-mono);letter-spacing:.09em}.exercise-brief>strong{font-size:clamp(20px,2.6vw,34px);line-height:1.12}.exercise-brief>div{grid-column:2;color:#afbec7;font:500 9px var(--font-mono);letter-spacing:.05em}.exercise-brief b{margin-left:18px;color:var(--accent)}.exercise-brief b:first-child{margin-left:0}
|
||||
.prompt-compare{display:grid;grid-template-columns:1fr 1fr;gap:1px;margin-top:1px;background:var(--line)}.prompt-card{display:grid;grid-template-rows:auto 1fr auto;min-width:0;min-height:600px;color:var(--paper);background:#19364a}.prompt-card.enhanced{background:#596f9a}.prompt-card header{display:flex;justify-content:space-between;align-items:center;padding:20px 22px;border-bottom:1px solid #ffffff32}.prompt-card header>div{display:grid;gap:6px}.prompt-card header span,.prompt-card footer{font:500 8px var(--font-mono);letter-spacing:.09em}.prompt-card header>div span{color:var(--gold)}.prompt-card header strong{font-size:17px}.prompt-card button{display:flex;align-items:center;gap:12px;padding:10px 12px;border:1px solid #ffffff50;color:var(--paper);background:transparent;cursor:pointer}.prompt-card button:hover,.prompt-card button.copied{color:var(--ink);border-color:var(--gold);background:var(--gold)}.prompt-card button i{font-style:normal}.prompt-card pre{margin:0;padding:25px;overflow:auto;white-space:pre-wrap}.prompt-card pre code{font:11px/1.72 var(--font-mono)}.prompt-card footer{padding:17px 22px;color:#bfccd4;border-top:1px solid #ffffff32}.prompt-card.enhanced footer{color:#e5e3ef}.prompt-card button:focus-visible,.starter-link:focus-visible{outline:3px solid var(--gold);outline-offset:3px}
|
||||
.comparison-strip{display:grid;grid-template-columns:190px repeat(4,1fr);gap:1px;background:var(--line)}.comparison-strip>*{padding:18px;background:var(--paper)}.comparison-strip>span{color:var(--accent);font:700 9px var(--font-mono);letter-spacing:.08em}.comparison-strip>div{color:var(--muted);font:500 10px var(--font-mono)}.comparison-strip b{margin-right:8px;color:var(--blue)}.copy-status{min-height:20px;margin:15px 0 0;color:var(--blue);font:600 10px var(--font-mono);text-align:right}
|
||||
@media(min-width:1600px){.tree-stage{height:390px}.tree-stage svg{height:330px;top:30px}.tree-node.root{top:45px}.tree-node.branch{top:255px}.tree-node{width:190px;padding:17px}.tree-detail{grid-template-columns:.6fr .8fr 1.8fr}.worker-card{min-height:210px;padding:28px}}
|
||||
@media(min-width:2200px){main{max-width:2880px;padding-inline:clamp(140px,7vw,280px)}.hero{max-width:1420px}.hero h1{font-size:clamp(150px,7vw,220px)}.tree-stage{height:460px}.tree-stage svg{height:380px;top:45px}.tree-node.root{top:65px}.tree-node.branch{top:305px}.tree-node{width:240px;padding:22px}.tree-node strong{font-size:15px}.tree-detail>*{font-size:14px!important}.fleet,.failure-map{margin-bottom:170px}.workflow,.routing,.skills{margin-bottom:180px}}
|
||||
@media(max-width:1100px){.chapter-links{display:none}.builder-workbench{grid-template-columns:minmax(210px,.65fr) minmax(0,1.35fr)}.builder-artifact{grid-column:1/-1;grid-template-columns:1fr 1fr;grid-template-rows:auto}.builder-artifact .artifact-head{grid-column:1/-1}.artifact-command{align-content:center;border-top:0;border-left:1px solid #344c5d}}
|
||||
|
||||
+1
-1
File diff suppressed because one or more lines are too long
+349
-43
@@ -24,68 +24,374 @@ const skillsHtml = read('skills/index.html');
|
||||
const reviewCatalog = read('skills-review/catalog.js');
|
||||
const reviewVoteJs = read('skills-review/vote.js');
|
||||
const voteService = read('vote-service/main.go');
|
||||
for (const url of ['https://code.claude.com/docs/en/sub-agents','https://code.claude.com/docs/en/skills','https://code.claude.com/docs/en/worktrees','https://git-scm.com/docs/git-worktree.html','https://developers.openai.com/codex/skills']) if (!refs.includes(url)) throw new Error(`missing reference ${url}`);
|
||||
for (const url of [
|
||||
'https://code.claude.com/docs/en/sub-agents',
|
||||
'https://code.claude.com/docs/en/skills',
|
||||
'https://code.claude.com/docs/en/worktrees',
|
||||
'https://git-scm.com/docs/git-worktree.html',
|
||||
'https://developers.openai.com/codex/skills',
|
||||
])
|
||||
if (!refs.includes(url)) throw new Error(`missing reference ${url}`);
|
||||
console.log('content verification passed');
|
||||
for (const token of ['data-phase="plan"','data-phase="build"','data-phase="review"','data-tree="main"','data-tree="ui"','data-worker="ui"','data-route="plan"','data-model-provider="openai"','data-model-provider="claude"','data-model-provider="gemini"','data-effort="low"','data-effort="medium"','data-effort="high"','data-skill-file="skill"','data-skill-step="observe"','data-skill-step="validate"','data-common-skill="ponytail"','data-common-skill="caveman"','data-common-skill="unlazy"','id="hands-on"','data-copy-target="prompt-install-skills"','data-copy-target="prompt-basic"','data-copy-target="prompt-skills"','hands-on/starter/','additional-reading.md','role="tablist"','<table']) if (!html.includes(token)) throw new Error(`missing content ${token}`);
|
||||
for (const token of ['const phases','const handsOnPrompts','const modelGuide','const skillSources','const skillInstallPrompts','addEventListener','render(\'plan\')','renderTree','renderWorker','renderRoute','renderModelProvider','renderEffort','renderSkillFile','renderSkillWorkflow','renderCommonSkill','renderHandsOn','copyPrompt']) if (!js.includes(token)) throw new Error(`missing interaction ${token}`);
|
||||
for (const token of ['id="task-list"','id="task-count"']) if (!starterHtml.includes(token)) throw new Error(`missing starter content ${token}`);
|
||||
for (const token of ['const tasks','renderTasks()']) if (!starterJs.includes(token)) throw new Error(`missing starter behavior ${token}`);
|
||||
for (const token of ['medium.com','anthropic.com/engineering','openai.com/business','git-scm.com/docs/git-worktree']) if (!additional.includes(token)) throw new Error(`missing additional source ${token}`);
|
||||
if ((additional.match(/^### \d+\./gm) || []).length < 5) throw new Error('fewer than five additional readings');
|
||||
for (const token of ['e7b42dc2d384a702240dea4d52a7bf5530b821b6','6654f6b60cd9d5be8b54c6fafe44346dabeb3b76','53048666b05b4799081517d00e09e0a2dd688678']) if (!skillSources.includes(token) || !js.includes(token)) throw new Error(`missing pinned skill source ${token}`);
|
||||
for (const token of ['developers.openai.com/api/docs/guides/latest-model','docs.anthropic.com/en/docs/claude-code/model-config','ai.google.dev/gemini-api/docs/thinking']) if (!modelRouting.includes(token) || !js.includes(token)) throw new Error(`missing model source ${token}`);
|
||||
for (const token of [
|
||||
'data-phase="plan"',
|
||||
'data-phase="build"',
|
||||
'data-phase="review"',
|
||||
'data-tree="main"',
|
||||
'data-tree="ui"',
|
||||
'data-worker="ui"',
|
||||
'data-route="plan"',
|
||||
'data-model-provider="openai"',
|
||||
'data-model-provider="claude"',
|
||||
'data-model-provider="gemini"',
|
||||
'data-effort="low"',
|
||||
'data-effort="medium"',
|
||||
'data-effort="high"',
|
||||
'data-skill-file="skill"',
|
||||
'data-skill-step="observe"',
|
||||
'data-skill-step="validate"',
|
||||
'data-common-skill="ponytail"',
|
||||
'data-common-skill="caveman"',
|
||||
'data-common-skill="unlazy"',
|
||||
'id="hands-on"',
|
||||
'data-copy-target="prompt-install-skills"',
|
||||
'data-copy-target="prompt-basic"',
|
||||
'data-copy-target="prompt-skills"',
|
||||
'hands-on/starter/',
|
||||
'additional-reading.md',
|
||||
'role="tablist"',
|
||||
'<table',
|
||||
])
|
||||
if (!html.includes(token)) throw new Error(`missing content ${token}`);
|
||||
for (const token of [
|
||||
'const phases',
|
||||
'const handsOnPrompts',
|
||||
'const modelGuide',
|
||||
'const skillSources',
|
||||
'const skillInstallPrompts',
|
||||
'addEventListener',
|
||||
"render('plan')",
|
||||
'renderTree',
|
||||
'renderWorker',
|
||||
'renderRoute',
|
||||
'renderModelProvider',
|
||||
'renderEffort',
|
||||
'renderSkillFile',
|
||||
'renderSkillWorkflow',
|
||||
'renderCommonSkill',
|
||||
'renderHandsOn',
|
||||
'copyPrompt',
|
||||
])
|
||||
if (!js.includes(token)) throw new Error(`missing interaction ${token}`);
|
||||
for (const token of ['id="task-list"', 'id="task-count"'])
|
||||
if (!starterHtml.includes(token)) throw new Error(`missing starter content ${token}`);
|
||||
for (const token of ['const tasks', 'renderTasks()'])
|
||||
if (!starterJs.includes(token)) throw new Error(`missing starter behavior ${token}`);
|
||||
for (const token of [
|
||||
'medium.com',
|
||||
'anthropic.com/engineering',
|
||||
'openai.com/business',
|
||||
'git-scm.com/docs/git-worktree',
|
||||
])
|
||||
if (!additional.includes(token)) throw new Error(`missing additional source ${token}`);
|
||||
if ((additional.match(/^### \d+\./gm) || []).length < 5)
|
||||
throw new Error('fewer than five additional readings');
|
||||
for (const token of [
|
||||
'e7b42dc2d384a702240dea4d52a7bf5530b821b6',
|
||||
'6654f6b60cd9d5be8b54c6fafe44346dabeb3b76',
|
||||
'53048666b05b4799081517d00e09e0a2dd688678',
|
||||
])
|
||||
if (!skillSources.includes(token) || !js.includes(token))
|
||||
throw new Error(`missing pinned skill source ${token}`);
|
||||
for (const token of [
|
||||
'developers.openai.com/api/docs/guides/latest-model',
|
||||
'docs.anthropic.com/en/docs/claude-code/model-config',
|
||||
'ai.google.dev/gemini-api/docs/thinking',
|
||||
])
|
||||
if (!modelRouting.includes(token) || !js.includes(token))
|
||||
throw new Error(`missing model source ${token}`);
|
||||
console.log('interaction verification passed');
|
||||
if (html.match(/<(script|link)[^>]+(src|href)="https?:[^"]+"/i)) throw new Error('external runtime dependency found');
|
||||
if (html.match(/<(script|link)[^>]+(src|href)="https?:[^"]+"/i))
|
||||
throw new Error('external runtime dependency found');
|
||||
console.log('standalone verification passed');
|
||||
for (const token of ['id="pipeline"','id="skills"','id="examples"','data-stage="context"','data-stage="cli"','data-stage="commit"','data-stage="review"','gate-discipline','parallel-agents','repo-db','tech-debt','skill-writer','scripts/check-ui-contract.mjs','.husky/pre-commit','.pr-review.json','.agents/skills','netcracker/interview']) if (!rulesHtml.includes(token)) throw new Error(`missing rules content ${token}`);
|
||||
for (const token of [
|
||||
'id="pipeline"',
|
||||
'id="skills"',
|
||||
'id="examples"',
|
||||
'data-stage="context"',
|
||||
'data-stage="cli"',
|
||||
'data-stage="commit"',
|
||||
'data-stage="review"',
|
||||
'gate-discipline',
|
||||
'parallel-agents',
|
||||
'repo-db',
|
||||
'tech-debt',
|
||||
'skill-writer',
|
||||
'scripts/check-ui-contract.mjs',
|
||||
'.husky/pre-commit',
|
||||
'.pr-review.json',
|
||||
'.agents/skills',
|
||||
'netcracker/interview',
|
||||
])
|
||||
if (!rulesHtml.includes(token)) throw new Error(`missing rules content ${token}`);
|
||||
console.log('rules content verification passed');
|
||||
for (const token of ['const languageCopy','const stages','const skills','const prompts','renderStage','renderSkill','renderLanguage','copyPrompt','addEventListener']) if (!rulesJs.includes(token)) throw new Error(`missing rules interaction ${token}`);
|
||||
for (const token of ['data-lang="en"','data-lang="pt"','data-copy-prompt','aria-live="polite"','role="tablist"']) if (!rulesHtml.includes(token)) throw new Error(`missing rules control ${token}`);
|
||||
for (const token of [
|
||||
'const languageCopy',
|
||||
'const stages',
|
||||
'const skills',
|
||||
'const prompts',
|
||||
'renderStage',
|
||||
'renderSkill',
|
||||
'renderLanguage',
|
||||
'copyPrompt',
|
||||
'addEventListener',
|
||||
])
|
||||
if (!rulesJs.includes(token)) throw new Error(`missing rules interaction ${token}`);
|
||||
for (const token of [
|
||||
'data-lang="en"',
|
||||
'data-lang="pt"',
|
||||
'data-copy-prompt',
|
||||
'aria-live="polite"',
|
||||
'role="tablist"',
|
||||
])
|
||||
if (!rulesHtml.includes(token)) throw new Error(`missing rules control ${token}`);
|
||||
console.log('rules interaction verification passed');
|
||||
if (!html.includes('href="../rules/"')) throw new Error('main presentation does not link to rules page');
|
||||
if (!html.includes('href="../skills-review/"')) throw new Error('main presentation does not link to skills review page');
|
||||
for (const token of ['../summary/','../models/','../agents/','../skills/','chapter-route']) if (!html.includes(token)) throw new Error(`main presentation missing chapter route ${token}`);
|
||||
if (rulesHtml.includes('script src="http') || rulesHtml.includes('rel="stylesheet" href="http')) throw new Error('rules page has an external runtime dependency');
|
||||
for (const token of ['@media(min-width:2200px)','@media(max-width:900px)','@media(max-width:600px)','prefers-reduced-motion']) if (!rulesCss.includes(token)) throw new Error(`missing rules responsive contract ${token}`);
|
||||
if (!html.includes('href="../rules/"'))
|
||||
throw new Error('main presentation does not link to rules page');
|
||||
if (!html.includes('href="../skills-review/"'))
|
||||
throw new Error('main presentation does not link to skills review page');
|
||||
for (const token of ['../summary/', '../models/', '../agents/', '../skills/', 'chapter-route'])
|
||||
if (!html.includes(token)) throw new Error(`main presentation missing chapter route ${token}`);
|
||||
if (rulesHtml.includes('script src="http') || rulesHtml.includes('rel="stylesheet" href="http'))
|
||||
throw new Error('rules page has an external runtime dependency');
|
||||
for (const token of [
|
||||
'@media(min-width:2200px)',
|
||||
'@media(max-width:900px)',
|
||||
'@media(max-width:600px)',
|
||||
'prefers-reduced-motion',
|
||||
])
|
||||
if (!rulesCss.includes(token)) throw new Error(`missing rules responsive contract ${token}`);
|
||||
console.log('rules standalone verification passed');
|
||||
for (const token of ['id="catalog"','id="skill-filter"','id="skill-list"','id="detail"','Preview Markdown','styles.css?v=20260904-vote-widget','change-lens.css?v=20260904-vote-widget','app.js?v=20260904-vote-widget','?author=Name&skill=skill-id&view=improved','SKILLS_REVIEW_VOTE_API']) if (!reviewHtml.includes(token)) throw new Error(`missing review page content ${token}`);
|
||||
for (const token of ["from './catalog.js'", "from './files.js'",'function renderList','function renderDetail','selectSkill','packageSummary','markdownHeadings','markdownToc','document.addEventListener(\'keydown\'','loadSelectedFile','schedulePackageSearch','fetchSource','packageSearchText','diffMarkup','diffRows','data-diff','searchParams.set(\'compare\'','markdownMarkup','data-render','preview-markdown','Preview Markdown','View source','FILE PREVIEW','searchParams.set(\'render\'','AUTHOR ·','SKILL ·','function selectFromUrl','function syncUrl','URLSearchParams','navigator.clipboard','document.execCommand','download','data-file','searchParams.set(\'file\'']) if (!reviewJs.includes(token)) throw new Error(`missing review interaction ${token}`);
|
||||
for (const token of ['ndo-repro','gfiber-logging','confluence-page','diagram-plantuml','page-reviewer','unslop','spanish-naturalizer','draft-mr','semantic-diff-review','reference.md','files =']) if (!`${reviewFiles}\n${read('skills-review/submitted-files.js')}`.includes(token)) throw new Error(`missing review file manifest ${token}`);
|
||||
if ((reviewCatalog.match(/id:'/g) || []).length + (read('skills-review/submitted-catalog.js').match(/id:'/g) || []).length !== 24) throw new Error('review catalog does not cover all submissions');
|
||||
if (!reviewCatalog.includes('hardcoded password') || !reviewCatalog.includes('safety-redacted') || !reviewJs.includes('[REDACTED]') || !reviewJs.includes('[REDACTED LOCAL USER]') || !reviewJs.includes('[REDACTED USER]')) throw new Error('review catalog does not record secret safety handling');
|
||||
for (const token of [
|
||||
'id="catalog"',
|
||||
'id="skill-filter"',
|
||||
'id="skill-list"',
|
||||
'id="detail"',
|
||||
'Preview Markdown',
|
||||
'styles.css?v=20260904-vote-widget',
|
||||
'change-lens.css?v=20260904-vote-widget',
|
||||
'app.js?v=20260904-vote-widget',
|
||||
'?author=Name&skill=skill-id&view=improved',
|
||||
'SKILLS_REVIEW_VOTE_API',
|
||||
])
|
||||
if (!reviewHtml.includes(token)) throw new Error(`missing review page content ${token}`);
|
||||
for (const token of [
|
||||
"from './catalog.js'",
|
||||
"from './files.js'",
|
||||
'function renderList',
|
||||
'function renderDetail',
|
||||
'selectSkill',
|
||||
'packageSummary',
|
||||
'markdownHeadings',
|
||||
'markdownToc',
|
||||
"document.addEventListener('keydown'",
|
||||
'loadSelectedFile',
|
||||
'schedulePackageSearch',
|
||||
'fetchSource',
|
||||
'packageSearchText',
|
||||
'diffMarkup',
|
||||
'diffRows',
|
||||
'data-diff',
|
||||
"searchParams.set('compare'",
|
||||
'markdownMarkup',
|
||||
'data-render',
|
||||
'preview-markdown',
|
||||
'Preview Markdown',
|
||||
'View source',
|
||||
'FILE PREVIEW',
|
||||
"searchParams.set('render'",
|
||||
'AUTHOR ·',
|
||||
'SKILL ·',
|
||||
'function selectFromUrl',
|
||||
'function syncUrl',
|
||||
'URLSearchParams',
|
||||
'navigator.clipboard',
|
||||
'document.execCommand',
|
||||
'download',
|
||||
'data-file',
|
||||
"searchParams.set('file'",
|
||||
])
|
||||
if (!reviewJs.includes(token)) throw new Error(`missing review interaction ${token}`);
|
||||
for (const token of [
|
||||
'ndo-repro',
|
||||
'gfiber-logging',
|
||||
'confluence-page',
|
||||
'diagram-plantuml',
|
||||
'page-reviewer',
|
||||
'unslop',
|
||||
'spanish-naturalizer',
|
||||
'draft-mr',
|
||||
'semantic-diff-review',
|
||||
'reference.md',
|
||||
'files =',
|
||||
])
|
||||
if (!`${reviewFiles}\n${read('skills-review/submitted-files.js')}`.includes(token))
|
||||
throw new Error(`missing review file manifest ${token}`);
|
||||
if (
|
||||
(reviewCatalog.match(/id:'/g) || []).length +
|
||||
(read('skills-review/submitted-catalog.js').match(/id:'/g) || []).length !==
|
||||
24
|
||||
)
|
||||
throw new Error('review catalog does not cover all submissions');
|
||||
if (
|
||||
!reviewCatalog.includes('hardcoded password') ||
|
||||
!reviewCatalog.includes('safety-redacted') ||
|
||||
!reviewJs.includes('[REDACTED]') ||
|
||||
!reviewJs.includes('[REDACTED LOCAL USER]') ||
|
||||
!reviewJs.includes('[REDACTED USER]')
|
||||
)
|
||||
throw new Error('review catalog does not record secret safety handling');
|
||||
console.log('skills review verification passed');
|
||||
for (const page of [summaryHtml, modelsHtml, agentsHtml, skillsHtml]) if (!page.includes('../chapters.css') || !page.includes('ROUTE MAP')) throw new Error('chapter page missing shared navigation');
|
||||
for (const token of ['--ink','@media(max-width:800px)','@media(max-width:520px)']) if (!chaptersCss.includes(token)) throw new Error(`missing chapter responsive contract ${token}`);
|
||||
for (const page of [summaryHtml, modelsHtml, agentsHtml, skillsHtml])
|
||||
if (!page.includes('../chapters.css') || !page.includes('ROUTE MAP'))
|
||||
throw new Error('chapter page missing shared navigation');
|
||||
for (const token of ['--ink', '@media(max-width:800px)', '@media(max-width:520px)'])
|
||||
if (!chaptersCss.includes(token)) throw new Error(`missing chapter responsive contract ${token}`);
|
||||
console.log('chapter route verification passed');
|
||||
for (const token of ['The short route','full-guide/','models/','agents/','skills/','rules/','hands-on/starter/','skills-review/']) if (!landingHtml.includes(token)) throw new Error(`landing page missing ${token}`);
|
||||
if (landingHtml.includes('app.js')) throw new Error('landing page should remain a fast, static route map');
|
||||
for (const token of [
|
||||
'The short route',
|
||||
'full-guide/',
|
||||
'models/',
|
||||
'agents/',
|
||||
'skills/',
|
||||
'rules/',
|
||||
'hands-on/starter/',
|
||||
'skills-review/',
|
||||
])
|
||||
if (!landingHtml.includes(token)) throw new Error(`landing page missing ${token}`);
|
||||
if (landingHtml.includes('app.js'))
|
||||
throw new Error('landing page should remain a fast, static route map');
|
||||
console.log('landing route verification passed');
|
||||
for (const token of ['data-package-file="skill"','data-package-file="references"','data-package-file="scripts"','data-package-file="assets"','id="package-preview"','script src="app.js"']) if (!skillsHtml.includes(token)) throw new Error(`skills anatomy missing ${token}`);
|
||||
for (const token of [
|
||||
'data-package-file="skill"',
|
||||
'data-package-file="references"',
|
||||
'data-package-file="scripts"',
|
||||
'data-package-file="assets"',
|
||||
'id="package-preview"',
|
||||
'script src="app.js"',
|
||||
])
|
||||
if (!skillsHtml.includes(token)) throw new Error(`skills anatomy missing ${token}`);
|
||||
const skillsApp = read('skills/app.js');
|
||||
const skillsCss = read('skills/styles.css');
|
||||
for (const token of ['const packageFiles','function renderPackage','addEventListener','renderPackage(\'skill\')']) if (!skillsApp.includes(token)) throw new Error(`skills anatomy interaction missing ${token}`);
|
||||
for (const token of ['grid-template-columns:minmax(190px','overflow-wrap:anywhere','@media(max-width:800px)','prefers-reduced-motion']) if (!skillsCss.includes(token)) throw new Error(`skills anatomy responsive contract missing ${token}`);
|
||||
for (const token of [
|
||||
'const packageFiles',
|
||||
'function renderPackage',
|
||||
'addEventListener',
|
||||
"renderPackage('skill')",
|
||||
])
|
||||
if (!skillsApp.includes(token)) throw new Error(`skills anatomy interaction missing ${token}`);
|
||||
for (const token of [
|
||||
'grid-template-columns:minmax(190px',
|
||||
'overflow-wrap:anywhere',
|
||||
'@media(max-width:800px)',
|
||||
'prefers-reduced-motion',
|
||||
])
|
||||
if (!skillsCss.includes(token))
|
||||
throw new Error(`skills anatomy responsive contract missing ${token}`);
|
||||
console.log('skills anatomy verification passed');
|
||||
console.log('presentation verification passed');
|
||||
const legacyName = String.fromCharCode(80, 101, 100, 114, 111, 32, 65, 114, 97, 110, 104, 97);
|
||||
const legacyHandle = legacyName.toLowerCase().replace(' ', '.');
|
||||
for (const path of ['submitted-skills/Anonymous Operational Submission/skills/ndo-repro/SKILL.md','submitted-skills/Anonymous Operational Submission/skills/ndo-repro/envs.tsv','submitted-skills/Anonymous Operational Submission/skills/ndo-repro/lib/env.sh','submitted-skills/Anonymous Operational Submission/skills/ndo-repro/ndo-api.sh','submitted-skills/Anonymous Operational Submission/skills/ndo-repro/ndo-ship.sh','submitted-skills/Anonymous Operational Submission/skills/ndo-repro/reference/bom-Dockerfile_local.example','submitted-skills/Anonymous Operational Submission/skills/ndo-repro/reference/dockerfile-local.md','skill-reviews/improved/ndo-repro/SKILL.md']) {
|
||||
for (const path of [
|
||||
'submitted-skills/Anonymous Operational Submission/skills/ndo-repro/SKILL.md',
|
||||
'submitted-skills/Anonymous Operational Submission/skills/ndo-repro/envs.tsv',
|
||||
'submitted-skills/Anonymous Operational Submission/skills/ndo-repro/lib/env.sh',
|
||||
'submitted-skills/Anonymous Operational Submission/skills/ndo-repro/ndo-api.sh',
|
||||
'submitted-skills/Anonymous Operational Submission/skills/ndo-repro/ndo-ship.sh',
|
||||
'submitted-skills/Anonymous Operational Submission/skills/ndo-repro/reference/bom-Dockerfile_local.example',
|
||||
'submitted-skills/Anonymous Operational Submission/skills/ndo-repro/reference/dockerfile-local.md',
|
||||
'skill-reviews/improved/ndo-repro/SKILL.md',
|
||||
]) {
|
||||
const source = read(path);
|
||||
if (new RegExp(`${legacyName}|${legacyHandle}|https?:\\/\\/|git\\.netcracker\\.com|artifactorycn|managed\\.netcracker\\.cloud`, 'i').test(source)) throw new Error(`operational submission privacy leak in ${path}`);
|
||||
if (
|
||||
new RegExp(
|
||||
`${legacyName}|${legacyHandle}|https?:\\/\\/|git\\.netcracker\\.com|artifactorycn|managed\\.netcracker\\.cloud`,
|
||||
'i',
|
||||
).test(source)
|
||||
)
|
||||
throw new Error(`operational submission privacy leak in ${path}`);
|
||||
}
|
||||
for (const source of [reviewCatalog, reviewFiles, reviewJs]) if (source.includes(legacyName) || source.includes(legacyName.replace(' ', '%20'))) throw new Error('operational submission identity remains in review desk source');
|
||||
if (!reviewFiles.includes('Anonymous%20Operational%20Submission') || !reviewJs.includes("entry.id === 'ndo-repro'")) throw new Error('operational submission redaction contract missing');
|
||||
for (const source of [reviewCatalog, reviewFiles, reviewJs])
|
||||
if (source.includes(legacyName) || source.includes(legacyName.replace(' ', '%20')))
|
||||
throw new Error('operational submission identity remains in review desk source');
|
||||
if (
|
||||
!reviewFiles.includes('Anonymous%20Operational%20Submission') ||
|
||||
!reviewJs.includes("entry.id === 'ndo-repro'")
|
||||
)
|
||||
throw new Error('operational submission redaction contract missing');
|
||||
console.log('review privacy verification passed');
|
||||
for (const token of ['currentContent','unchangedDraft','state.preview = button.dataset.preview','state.file = available.find','loadSelectedFile']) if (!reviewJs.includes(token)) throw new Error(`review file-mode contract missing ${token}`);
|
||||
if (reviewJs.includes("state.preview = 'original'; syncUrl(); renderDetail(); loadSelectedFile();")) throw new Error('file selection still resets improved mode');
|
||||
for (const token of [
|
||||
'currentContent',
|
||||
'unchangedDraft',
|
||||
'state.preview = button.dataset.preview',
|
||||
'state.file = available.find',
|
||||
'loadSelectedFile',
|
||||
])
|
||||
if (!reviewJs.includes(token)) throw new Error(`review file-mode contract missing ${token}`);
|
||||
if (reviewJs.includes("state.preview = 'original'; syncUrl(); renderDetail(); loadSelectedFile();"))
|
||||
throw new Error('file selection still resets improved mode');
|
||||
console.log('review file-mode verification passed');
|
||||
for (const token of ['const changeRows','function lensMarkup','data-lens','CHANGE LENS','What changed — and why.']) if (!reviewJs.includes(token)) throw new Error(`review change-lens contract missing ${token}`);
|
||||
for (const token of ['.change-lens','.change-rows','.skill-diff','.diff-lines','@media(max-width:620px)','prefers-reduced-motion']) if (!reviewLensCss.includes(token)) throw new Error(`review change-lens CSS missing ${token}`);
|
||||
for (const token of [
|
||||
'const changeRows',
|
||||
'function lensMarkup',
|
||||
'data-lens',
|
||||
'CHANGE LENS',
|
||||
'What changed — and why.',
|
||||
])
|
||||
if (!reviewJs.includes(token)) throw new Error(`review change-lens contract missing ${token}`);
|
||||
for (const token of [
|
||||
'.change-lens',
|
||||
'.change-rows',
|
||||
'.skill-diff',
|
||||
'.diff-lines',
|
||||
'@media(max-width:620px)',
|
||||
'prefers-reduced-motion',
|
||||
])
|
||||
if (!reviewLensCss.includes(token)) throw new Error(`review change-lens CSS missing ${token}`);
|
||||
console.log('review change-lens verification passed');
|
||||
for (const token of ['.markdown-preview','max-height:540px','.markdown-table-wrap','.markdown-frontmatter','.markdown-toc','.preview-title','.preview-markdown','grid-template-columns:minmax(0,1fr)','height:120px','-webkit-line-clamp:2']) if (!read('skills-review/styles.css').includes(token)) throw new Error(`review markdown preview contract missing ${token}`);
|
||||
for (const token of [
|
||||
'.markdown-preview',
|
||||
'max-height:540px',
|
||||
'.markdown-table-wrap',
|
||||
'.markdown-frontmatter',
|
||||
'.markdown-toc',
|
||||
'.preview-title',
|
||||
'.preview-markdown',
|
||||
'grid-template-columns:minmax(0,1fr)',
|
||||
'height:120px',
|
||||
'-webkit-line-clamp:2',
|
||||
])
|
||||
if (!read('skills-review/styles.css').includes(token))
|
||||
throw new Error(`review markdown preview contract missing ${token}`);
|
||||
console.log('review markdown preview verification passed');
|
||||
for (const token of ["from './vote.js'","renderVoteWidget($('#vote-widget'"]) if (!reviewJs.includes(token)) throw new Error(`review vote widget wiring missing ${token}`);
|
||||
for (const token of ['id="vote-widget"','function renderVoteWidget','X-Voter-Id','/api/votes','Voting is offline']) if (!reviewVoteJs.includes(token) && !reviewJs.includes(token)) throw new Error(`review vote widget contract missing ${token}`);
|
||||
for (const token of ['.vote-widget','.vote-buttons','[aria-pressed="true"]']) if (!read('skills-review/styles.css').includes(token)) throw new Error(`review vote widget CSS missing ${token}`);
|
||||
if (!voteService.includes('X-Forwarded-For') || !voteService.includes('one active vote per skill') && !voteService.includes('at most one active vote')) throw new Error('vote-service missing IP-based one-vote-per-source contract');
|
||||
for (const token of ["from './vote.js'", "renderVoteWidget($('#vote-widget'"])
|
||||
if (!reviewJs.includes(token)) throw new Error(`review vote widget wiring missing ${token}`);
|
||||
for (const token of [
|
||||
'id="vote-widget"',
|
||||
'function renderVoteWidget',
|
||||
'X-Voter-Id',
|
||||
'/api/votes',
|
||||
'Voting is offline',
|
||||
])
|
||||
if (!reviewVoteJs.includes(token) && !reviewJs.includes(token))
|
||||
throw new Error(`review vote widget contract missing ${token}`);
|
||||
for (const token of ['.vote-widget', '.vote-buttons', '[aria-pressed="true"]'])
|
||||
if (!read('skills-review/styles.css').includes(token))
|
||||
throw new Error(`review vote widget CSS missing ${token}`);
|
||||
if (
|
||||
!voteService.includes('X-Forwarded-For') ||
|
||||
(!voteService.includes('one active vote per skill') &&
|
||||
!voteService.includes('at most one active vote'))
|
||||
)
|
||||
throw new Error('vote-service missing IP-based one-vote-per-source contract');
|
||||
console.log('review vote widget verification passed');
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
.change-lens{border:1px solid var(--ink);background:#123042;color:var(--paper);animation:lens-enter .28s ease both}.change-lens>header{display:flex;justify-content:space-between;gap:20px;align-items:start;padding:22px 24px;border-bottom:1px solid #466274}.change-lens span{color:var(--gold);font:700 10px ui-monospace,monospace;letter-spacing:.1em}.change-lens h3{margin:7px 0 0;font-size:clamp(24px,3vw,40px);line-height:1.02;letter-spacing:-.05em}.change-lens>header button{padding:9px 11px;border:1px solid #557080;color:var(--paper);background:transparent;cursor:pointer;font:700 10px ui-monospace,monospace}.change-lens>header button:hover{color:var(--ink);background:var(--gold)}.change-lens>p{max-width:67ch;margin:0;padding:19px 24px;color:#c6d2d7}.change-rows{display:grid;gap:1px;background:#466274}.change-rows article{display:grid;grid-template-columns:120px minmax(0,1fr) minmax(0,1fr) minmax(220px,.85fr);gap:1px;background:#466274}.change-rows article>*{min-width:0;margin:0;padding:17px;background:#173b4f}.change-rows article>span{color:var(--gold);font:700 10px/1.4 ui-monospace,monospace}.change-rows b{font:700 10px ui-monospace,monospace;letter-spacing:.07em;text-transform:uppercase}.change-rows div:first-of-type b{color:#e89a8e}.change-rows div:nth-of-type(2) b{color:#9bcba7}.change-rows aside{background:#1d455b}.change-rows aside b{color:var(--gold)}.change-rows p{margin:7px 0 0;color:#d4dfe3;font-size:12px;line-height:1.55}.preview header [data-lens]{color:var(--gold);border-color:var(--gold)}@keyframes lens-enter{from{opacity:.15;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}@media(max-width:1000px){.change-rows article{grid-template-columns:100px 1fr 1fr}.change-rows aside{grid-column:2/-1}}@media(max-width:620px){.change-lens>header{display:block}.change-lens>header button{margin-top:14px}.change-rows article{grid-template-columns:1fr}.change-rows article>span{padding-bottom:6px}.change-rows aside{grid-column:auto}.change-lens>p{padding:17px}.change-lens>header{padding:18px}.change-rows p{font-size:13px}}@media(prefers-reduced-motion:reduce){.change-lens{animation:none}}
|
||||
.change-lens{border:1px solid var(--ink);background:#123042;color:var(--paper);animation:lens-enter .28s ease both}.change-lens>header{display:flex;justify-content:space-between;gap:20px;align-items:start;padding:22px 24px;border-bottom:1px solid #466274}.change-lens span{color:var(--gold);font:700 10px var(--font-mono);letter-spacing:.1em}.change-lens h3{margin:7px 0 0;font-size:clamp(24px,3vw,40px);line-height:1.02;letter-spacing:-.05em}.change-lens>header button{padding:9px 11px;border:1px solid #557080;color:var(--paper);background:transparent;cursor:pointer;font:700 10px var(--font-mono)}.change-lens>header button:hover{color:var(--ink);background:var(--gold)}.change-lens>p{max-width:67ch;margin:0;padding:19px 24px;color:#c6d2d7}.change-rows{display:grid;gap:1px;background:#466274}.change-rows article{display:grid;grid-template-columns:120px minmax(0,1fr) minmax(0,1fr) minmax(220px,.85fr);gap:1px;background:#466274}.change-rows article>*{min-width:0;margin:0;padding:17px;background:#173b4f}.change-rows article>span{color:var(--gold);font:700 10px/1.4 var(--font-mono)}.change-rows b{font:700 10px var(--font-mono);letter-spacing:.07em;text-transform:uppercase}.change-rows div:first-of-type b{color:#e89a8e}.change-rows div:nth-of-type(2) b{color:#9bcba7}.change-rows aside{background:#1d455b}.change-rows aside b{color:var(--gold)}.change-rows p{margin:7px 0 0;color:#d4dfe3;font-size:12px;line-height:1.55}.preview header [data-lens]{color:var(--gold);border-color:var(--gold)}@keyframes lens-enter{from{opacity:.15;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}@media(max-width:1000px){.change-rows article{grid-template-columns:100px 1fr 1fr}.change-rows aside{grid-column:2/-1}}@media(max-width:620px){.change-lens>header{display:block}.change-lens>header button{margin-top:14px}.change-rows article{grid-template-columns:1fr}.change-rows article>span{padding-bottom:6px}.change-rows aside{grid-column:auto}.change-lens>p{padding:17px}.change-lens>header{padding:18px}.change-rows p{font-size:13px}}@media(prefers-reduced-motion:reduce){.change-lens{animation:none}}
|
||||
|
||||
/* A compact, scrollable comparison keeps long skill revisions reviewable. */
|
||||
.skill-diff{border:1px solid var(--ink);background:#102b3a;color:var(--paper);animation:lens-enter .28s ease both}.skill-diff>header{display:flex;justify-content:space-between;gap:20px;align-items:start;padding:22px 24px;border-bottom:1px solid #466274}.skill-diff span{color:var(--gold);font:700 10px ui-monospace,monospace;letter-spacing:.1em}.skill-diff h3{margin:7px 0 0;font-size:clamp(24px,3vw,40px);line-height:1.02;letter-spacing:-.05em}.skill-diff>header button{padding:9px 11px;border:1px solid #557080;color:var(--paper);background:transparent;cursor:pointer;font:700 10px ui-monospace,monospace}.skill-diff>header button:hover{color:var(--ink);background:var(--gold)}.skill-diff>p{margin:0;padding:17px 24px;color:#c6d2d7}.diff-lines{max-height:540px;overflow:auto;border-top:1px solid #466274;font:12px/1.55 ui-monospace,monospace}.diff-lines p{display:grid;grid-template-columns:42px minmax(0,1fr);gap:11px;margin:0;padding:4px 16px;white-space:pre-wrap;overflow-wrap:anywhere}.diff-lines span{color:#91aab7}.diff-lines .added{color:#d5f1d6;background:#1a4b42}.diff-lines .added span{color:#a9e3ae}.diff-lines .removed{color:#ffd7d0;background:#572f32}.diff-lines .removed span{color:#ffb5a8}.preview header [data-diff]{color:#c6d2d7;border-color:#557080}@media(max-width:620px){.skill-diff>header{display:block}.skill-diff>header button{margin-top:14px}.diff-lines p{grid-template-columns:30px minmax(0,1fr);padding:4px 12px}}@media(prefers-reduced-motion:reduce){.skill-diff{animation:none}}
|
||||
.skill-diff{border:1px solid var(--ink);background:#102b3a;color:var(--paper);animation:lens-enter .28s ease both}.skill-diff>header{display:flex;justify-content:space-between;gap:20px;align-items:start;padding:22px 24px;border-bottom:1px solid #466274}.skill-diff span{color:var(--gold);font:700 10px var(--font-mono);letter-spacing:.1em}.skill-diff h3{margin:7px 0 0;font-size:clamp(24px,3vw,40px);line-height:1.02;letter-spacing:-.05em}.skill-diff>header button{padding:9px 11px;border:1px solid #557080;color:var(--paper);background:transparent;cursor:pointer;font:700 10px var(--font-mono)}.skill-diff>header button:hover{color:var(--ink);background:var(--gold)}.skill-diff>p{margin:0;padding:17px 24px;color:#c6d2d7}.diff-lines{max-height:540px;overflow:auto;border-top:1px solid #466274;font:12px/1.55 var(--font-mono)}.diff-lines p{display:grid;grid-template-columns:42px minmax(0,1fr);gap:11px;margin:0;padding:4px 16px;white-space:pre-wrap;overflow-wrap:anywhere}.diff-lines span{color:#91aab7}.diff-lines .added{color:#d5f1d6;background:#1a4b42}.diff-lines .added span{color:#a9e3ae}.diff-lines .removed{color:#ffd7d0;background:#572f32}.diff-lines .removed span{color:#ffb5a8}.preview header [data-diff]{color:#c6d2d7;border-color:#557080}@media(max-width:620px){.skill-diff>header{display:block}.skill-diff>header button{margin-top:14px}.diff-lines p{grid-template-columns:30px minmax(0,1fr);padding:4px 12px}}@media(prefers-reduced-motion:reduce){.skill-diff{animation:none}}
|
||||
|
||||
File diff suppressed because one or more lines are too long
+1
-1
@@ -1 +1 @@
|
||||
.top > *{min-width:0}.top a{overflow-wrap:anywhere}.package-hint{max-width:27ch;color:var(--muted)}.package-workbench{display:grid;grid-template-columns:minmax(190px,.85fr) minmax(0,1.3fr);min-width:0;background:var(--ink);border:1px solid var(--ink);box-shadow:10px 10px 0 color-mix(in srgb,var(--gold) 55%,transparent)}.package-tree{padding:22px 16px;border-right:1px solid #426070;min-width:0}.package-tree>p,.package-preview>span{margin:0 0 14px;color:var(--gold);font:700 11px/1.35 ui-monospace,monospace;letter-spacing:.1em}.package-tree button{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:8px;width:100%;padding:12px 8px;border:0;border-left:2px solid transparent;background:transparent;color:#d6e1e4;text-align:left;cursor:pointer;transition:background .2s ease,border-color .2s ease,transform .2s ease}.package-tree button:hover,.package-tree button:focus-visible,.package-tree button.active{border-left-color:var(--gold);background:#1f3a4b;outline:0}.package-tree button:hover{transform:translateX(3px)}.package-tree code{min-width:0;overflow-wrap:anywhere;font:700 13px/1.4 ui-monospace,monospace}.package-tree small{color:#aebfc7;font:11px/1.25 Arial,sans-serif;text-align:right}.package-preview{min-width:0;padding:26px;background:#173245;color:var(--paper)}.package-preview h3{margin:0 0 8px;font-size:clamp(24px,3vw,38px);line-height:1.02;letter-spacing:-.045em}.package-preview p{max-width:52ch;margin:0;color:#d6e1e4}.package-preview pre{max-width:100%;margin:20px 0 0;padding:15px;overflow:auto;border:1px solid #466274;background:#102837;color:#d6e1e4;font:12px/1.55 ui-monospace,monospace}.package-preview.is-swapping{animation:package-preview-in .34s ease both}@keyframes package-preview-in{from{opacity:.25;transform:translateY(7px)}to{opacity:1;transform:translateY(0)}}.links a{transition:background .2s ease,color .2s ease,transform .2s ease}.links a:hover{transform:translateY(-2px)}@media(max-width:800px){.package-workbench{grid-template-columns:1fr}.package-tree{border-right:0;border-bottom:1px solid #426070}.package-preview{padding:22px}}@media(max-width:520px){.top{gap:12px}.top a{font-size:10px}.package-tree{padding:18px 10px}.package-tree button{padding:12px 6px}.package-tree small{display:none}.package-preview{padding:18px}.package-preview pre{font-size:11px}}@media(prefers-reduced-motion:reduce){*,*::before,*::after{scroll-behavior:auto!important;animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important}}
|
||||
.top > *{min-width:0}.top a{overflow-wrap:anywhere}.package-hint{max-width:27ch;color:var(--muted)}.package-workbench{display:grid;grid-template-columns:minmax(190px,.85fr) minmax(0,1.3fr);min-width:0;background:var(--ink);border:1px solid var(--ink);box-shadow:10px 10px 0 color-mix(in srgb,var(--gold) 55%,transparent)}.package-tree{padding:22px 16px;border-right:1px solid #426070;min-width:0}.package-tree>p,.package-preview>span{margin:0 0 14px;color:var(--gold);font:700 11px/1.35 var(--font-mono);letter-spacing:.1em}.package-tree button{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:8px;width:100%;padding:12px 8px;border:0;border-left:2px solid transparent;background:transparent;color:#d6e1e4;text-align:left;cursor:pointer;transition:background .2s ease,border-color .2s ease,transform .2s ease}.package-tree button:hover,.package-tree button:focus-visible,.package-tree button.active{border-left-color:var(--gold);background:#1f3a4b;outline:0}.package-tree button:hover{transform:translateX(3px)}.package-tree code{min-width:0;overflow-wrap:anywhere;font:700 13px/1.4 var(--font-mono)}.package-tree small{color:#aebfc7;font:11px/1.25 var(--font-sans);text-align:right}.package-preview{min-width:0;padding:26px;background:#173245;color:var(--paper)}.package-preview h3{margin:0 0 8px;font-size:clamp(24px,3vw,38px);line-height:1.02;letter-spacing:-.045em}.package-preview p{max-width:52ch;margin:0;color:#d6e1e4}.package-preview pre{max-width:100%;margin:20px 0 0;padding:15px;overflow:auto;border:1px solid #466274;background:#102837;color:#d6e1e4;font:12px/1.55 var(--font-mono)}.package-preview.is-swapping{animation:package-preview-in .34s ease both}@keyframes package-preview-in{from{opacity:.25;transform:translateY(7px)}to{opacity:1;transform:translateY(0)}}.links a{transition:background .2s ease,color .2s ease,transform .2s ease}.links a:hover{transform:translateY(-2px)}@media(max-width:800px){.package-workbench{grid-template-columns:1fr}.package-tree{border-right:0;border-bottom:1px solid #426070}.package-preview{padding:22px}}@media(max-width:520px){.top{gap:12px}.top a{font-size:10px}.package-tree{padding:18px 10px}.package-tree button{padding:12px 6px}.package-tree small{display:none}.package-preview{padding:18px}.package-preview pre{font-size:11px}}@media(prefers-reduced-motion:reduce){*,*::before,*::after{scroll-behavior:auto!important;animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important}}
|
||||
|
||||
@@ -9,22 +9,24 @@
|
||||
// hairlines between worker cards; the parent background is an off-token seam
|
||||
// colour marked inline with `token-gap`.
|
||||
|
||||
type Localized = { en: string; pt: string };
|
||||
|
||||
interface Worker {
|
||||
/** Used as the `data-worker` hook and the key in the source. */
|
||||
id: string;
|
||||
/** Short label rendered uppercase, e.g. "UI". */
|
||||
label: string;
|
||||
label: string | Localized;
|
||||
/** Body copy describing the worker's remit. */
|
||||
strong: string;
|
||||
strong: string | Localized;
|
||||
/** Path label, e.g. "agent/ui". */
|
||||
code: string;
|
||||
}
|
||||
|
||||
interface Props {
|
||||
orchestrator: {
|
||||
eyebrow: string;
|
||||
eyebrow: string | Localized;
|
||||
/** May contain inline `<br>`; rendered with `set:html`. */
|
||||
title: string;
|
||||
title: string | Localized;
|
||||
code: string;
|
||||
};
|
||||
workers: Worker[];
|
||||
@@ -36,8 +38,32 @@ const { orchestrator, workers, initial = workers[0]?.id } = Astro.props;
|
||||
|
||||
<div class="fleet-grid">
|
||||
<article class="captain">
|
||||
<span class="captain-eyebrow">{orchestrator.eyebrow}</span>
|
||||
<span class="captain-eyebrow">
|
||||
{
|
||||
typeof orchestrator.eyebrow === 'string' ? (
|
||||
orchestrator.eyebrow
|
||||
) : (
|
||||
<>
|
||||
<>
|
||||
<span data-language-content="en">{orchestrator.eyebrow.en}</span>
|
||||
<span data-language-content="pt" hidden>
|
||||
{orchestrator.eyebrow.pt}
|
||||
</span>
|
||||
</>
|
||||
</>
|
||||
)
|
||||
}
|
||||
</span>
|
||||
{
|
||||
typeof orchestrator.title === 'string' ? (
|
||||
<h2 set:html={orchestrator.title} />
|
||||
) : (
|
||||
<>
|
||||
<h2 data-language-content="en" set:html={orchestrator.title.en} />
|
||||
<h2 data-language-content="pt" hidden set:html={orchestrator.title.pt} />
|
||||
</>
|
||||
)
|
||||
}
|
||||
<code>{orchestrator.code}</code>
|
||||
</article>
|
||||
<div class="arrow" aria-hidden="true">→</div>
|
||||
@@ -49,8 +75,30 @@ const { orchestrator, workers, initial = workers[0]?.id } = Astro.props;
|
||||
data-worker={worker.id}
|
||||
aria-pressed={worker.id === initial}
|
||||
>
|
||||
<span>{worker.label}</span>
|
||||
<strong>{worker.strong}</strong>
|
||||
<span>
|
||||
{typeof worker.label === 'string' ? (
|
||||
worker.label
|
||||
) : (
|
||||
<>
|
||||
<span data-language-content="en">{worker.label.en}</span>
|
||||
<span data-language-content="pt" hidden>
|
||||
{worker.label.pt}
|
||||
</span>
|
||||
</>
|
||||
)}
|
||||
</span>
|
||||
<strong>
|
||||
{typeof worker.strong === 'string' ? (
|
||||
worker.strong
|
||||
) : (
|
||||
<>
|
||||
<span data-language-content="en">{worker.strong.en}</span>
|
||||
<span data-language-content="pt" hidden>
|
||||
{worker.strong.pt}
|
||||
</span>
|
||||
</>
|
||||
)}
|
||||
</strong>
|
||||
<code>{worker.code}</code>
|
||||
</button>
|
||||
))
|
||||
|
||||
@@ -7,18 +7,20 @@
|
||||
// muted body) and lives here so the next page that needs it gets the same
|
||||
// beat for free.
|
||||
|
||||
type Localized = { en: string; pt: string };
|
||||
|
||||
interface Row {
|
||||
/** The package name, rendered as a `<th>` (column 1). */
|
||||
package: string;
|
||||
package: string | Localized;
|
||||
/** What the package contains (column 2). */
|
||||
contains: string;
|
||||
contains: string | Localized;
|
||||
/** Why this matters (column 3). */
|
||||
why: string;
|
||||
why: string | Localized;
|
||||
}
|
||||
|
||||
interface Props {
|
||||
/** Column headers in render order. */
|
||||
columns: [string, string, string];
|
||||
columns: [string | Localized, string | Localized, string | Localized];
|
||||
rows: Row[];
|
||||
}
|
||||
|
||||
@@ -28,18 +30,96 @@ const { columns, rows } = Astro.props;
|
||||
<table class="handoff-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{columns[0]}</th>
|
||||
<th>{columns[1]}</th>
|
||||
<th>{columns[2]}</th>
|
||||
<th>
|
||||
{
|
||||
typeof columns[0] === 'string' ? (
|
||||
columns[0]
|
||||
) : (
|
||||
<>
|
||||
<>
|
||||
<span data-language-content="en">{columns[0].en}</span>
|
||||
<span data-language-content="pt" hidden>
|
||||
{columns[0].pt}
|
||||
</span>
|
||||
</>
|
||||
</>
|
||||
)
|
||||
}
|
||||
</th>
|
||||
<th>
|
||||
{
|
||||
typeof columns[1] === 'string' ? (
|
||||
columns[1]
|
||||
) : (
|
||||
<>
|
||||
<>
|
||||
<span data-language-content="en">{columns[1].en}</span>
|
||||
<span data-language-content="pt" hidden>
|
||||
{columns[1].pt}
|
||||
</span>
|
||||
</>
|
||||
</>
|
||||
)
|
||||
}
|
||||
</th>
|
||||
<th>
|
||||
{
|
||||
typeof columns[2] === 'string' ? (
|
||||
columns[2]
|
||||
) : (
|
||||
<>
|
||||
<>
|
||||
<span data-language-content="en">{columns[2].en}</span>
|
||||
<span data-language-content="pt" hidden>
|
||||
{columns[2].pt}
|
||||
</span>
|
||||
</>
|
||||
</>
|
||||
)
|
||||
}
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{
|
||||
rows.map((row) => (
|
||||
<tr>
|
||||
<th scope="row">{row.package}</th>
|
||||
<td>{row.contains}</td>
|
||||
<td>{row.why}</td>
|
||||
<th scope="row">
|
||||
{typeof row.package === 'string' ? (
|
||||
row.package
|
||||
) : (
|
||||
<>
|
||||
<span data-language-content="en">{row.package.en}</span>
|
||||
<span data-language-content="pt" hidden>
|
||||
{row.package.pt}
|
||||
</span>
|
||||
</>
|
||||
)}
|
||||
</th>
|
||||
<td>
|
||||
{typeof row.contains === 'string' ? (
|
||||
row.contains
|
||||
) : (
|
||||
<>
|
||||
<span data-language-content="en">{row.contains.en}</span>
|
||||
<span data-language-content="pt" hidden>
|
||||
{row.contains.pt}
|
||||
</span>
|
||||
</>
|
||||
)}
|
||||
</td>
|
||||
<td>
|
||||
{typeof row.why === 'string' ? (
|
||||
row.why
|
||||
) : (
|
||||
<>
|
||||
<span data-language-content="en">{row.why.en}</span>
|
||||
<span data-language-content="pt" hidden>
|
||||
{row.why.pt}
|
||||
</span>
|
||||
</>
|
||||
)}
|
||||
</td>
|
||||
</tr>
|
||||
))
|
||||
}
|
||||
|
||||
@@ -8,18 +8,20 @@
|
||||
//
|
||||
// Every `data-phase` value is asserted by `scripts/verify.mjs`.
|
||||
|
||||
type Localized = { en: string; pt: string };
|
||||
|
||||
export type PhaseId = 'plan' | 'build' | 'review';
|
||||
|
||||
interface Phase {
|
||||
id: PhaseId;
|
||||
/** Two-letter label rendered in the tab, e.g. "PLAN". */
|
||||
label: string;
|
||||
label: string | Localized;
|
||||
/** Numeric prefix, e.g. "01". */
|
||||
number: string;
|
||||
title: string;
|
||||
body: string;
|
||||
title: string | Localized;
|
||||
body: string | Localized;
|
||||
/** Headline + small caption shown above the panel title. */
|
||||
meta: { deliverable: string; gate: string };
|
||||
meta: { deliverable: string | Localized; gate: string | Localized };
|
||||
/** Code-line evidence shown at the bottom of the panel. */
|
||||
evidence: string;
|
||||
}
|
||||
@@ -43,7 +45,17 @@ const active = phases.find((phase) => phase.id === initial) ?? phases[0];
|
||||
role="tab"
|
||||
aria-selected={phase.id === initial}
|
||||
>
|
||||
<b>{phase.number}</b> {phase.label}
|
||||
<b>{phase.number}</b>{' '}
|
||||
{typeof phase.label === 'string' ? (
|
||||
phase.label
|
||||
) : (
|
||||
<>
|
||||
<span data-language-content="en">{phase.label.en}</span>
|
||||
<span data-language-content="pt" hidden>
|
||||
{phase.label.pt}
|
||||
</span>
|
||||
</>
|
||||
)}
|
||||
</button>
|
||||
))
|
||||
}
|
||||
@@ -51,11 +63,71 @@ const active = phases.find((phase) => phase.id === initial) ?? phases[0];
|
||||
|
||||
<article class="phase-panel" id="phase-panel" aria-live="polite">
|
||||
<div class="phase-meta">
|
||||
<span>{active.meta.deliverable}</span>
|
||||
<small>{active.meta.gate}</small>
|
||||
<span>
|
||||
{
|
||||
typeof active.meta.deliverable === 'string' ? (
|
||||
active.meta.deliverable
|
||||
) : (
|
||||
<>
|
||||
<>
|
||||
<span data-language-content="en">{active.meta.deliverable.en}</span>
|
||||
<span data-language-content="pt" hidden>
|
||||
{active.meta.deliverable.pt}
|
||||
</span>
|
||||
</>
|
||||
</>
|
||||
)
|
||||
}
|
||||
</span>
|
||||
<small>
|
||||
{
|
||||
typeof active.meta.gate === 'string' ? (
|
||||
active.meta.gate
|
||||
) : (
|
||||
<>
|
||||
<>
|
||||
<span data-language-content="en">{active.meta.gate.en}</span>
|
||||
<span data-language-content="pt" hidden>
|
||||
{active.meta.gate.pt}
|
||||
</span>
|
||||
</>
|
||||
</>
|
||||
)
|
||||
}
|
||||
</small>
|
||||
</div>
|
||||
<h3>{active.title}</h3>
|
||||
<p>{active.body}</p>
|
||||
<h3>
|
||||
{
|
||||
typeof active.title === 'string' ? (
|
||||
active.title
|
||||
) : (
|
||||
<>
|
||||
<>
|
||||
<span data-language-content="en">{active.title.en}</span>
|
||||
<span data-language-content="pt" hidden>
|
||||
{active.title.pt}
|
||||
</span>
|
||||
</>
|
||||
</>
|
||||
)
|
||||
}
|
||||
</h3>
|
||||
<p>
|
||||
{
|
||||
typeof active.body === 'string' ? (
|
||||
active.body
|
||||
) : (
|
||||
<>
|
||||
<>
|
||||
<span data-language-content="en">{active.body.en}</span>
|
||||
<span data-language-content="pt" hidden>
|
||||
{active.body.pt}
|
||||
</span>
|
||||
</>
|
||||
</>
|
||||
)
|
||||
}
|
||||
</p>
|
||||
<code>{active.evidence}</code>
|
||||
</article>
|
||||
|
||||
|
||||
@@ -6,29 +6,79 @@
|
||||
// renders the column header + the four rows; task 15 will hydrate the
|
||||
// "route detail" panel to the right.
|
||||
|
||||
type Localized = { en: string; pt: string };
|
||||
|
||||
interface Route {
|
||||
id: 'plan' | 'build' | 'explore' | 'review' | string;
|
||||
/** Strong label, e.g. "Plan". */
|
||||
strong: string;
|
||||
strong: string | Localized;
|
||||
/** Profile descriptor, e.g. "strong / broad". */
|
||||
profile: string;
|
||||
profile: string | Localized;
|
||||
/** Prompt shape copy. */
|
||||
prompt: string;
|
||||
prompt: string | Localized;
|
||||
}
|
||||
|
||||
interface Props {
|
||||
routes: Route[];
|
||||
initial?: string;
|
||||
headWork?: string | Localized;
|
||||
headProfile?: string | Localized;
|
||||
headPromptShape?: string | Localized;
|
||||
}
|
||||
|
||||
const { routes, initial = routes[0]?.id ?? 'plan' } = Astro.props;
|
||||
const {
|
||||
routes,
|
||||
initial = routes[0]?.id ?? 'plan',
|
||||
headWork = 'Work',
|
||||
headProfile = 'Profile',
|
||||
headPromptShape = 'Prompt shape',
|
||||
} = Astro.props;
|
||||
---
|
||||
|
||||
<div class="route-table">
|
||||
<div class="head">
|
||||
<span>Work</span>
|
||||
<span>Profile</span>
|
||||
<span>Prompt shape</span>
|
||||
<span>
|
||||
{
|
||||
typeof headWork === 'string' ? (
|
||||
headWork
|
||||
) : (
|
||||
<>
|
||||
<span data-language-content="en">{headWork.en}</span>
|
||||
<span data-language-content="pt" hidden>
|
||||
{headWork.pt}
|
||||
</span>
|
||||
</>
|
||||
)
|
||||
}
|
||||
</span>
|
||||
<span>
|
||||
{
|
||||
typeof headProfile === 'string' ? (
|
||||
headProfile
|
||||
) : (
|
||||
<>
|
||||
<span data-language-content="en">{headProfile.en}</span>
|
||||
<span data-language-content="pt" hidden>
|
||||
{headProfile.pt}
|
||||
</span>
|
||||
</>
|
||||
)
|
||||
}
|
||||
</span>
|
||||
<span>
|
||||
{
|
||||
typeof headPromptShape === 'string' ? (
|
||||
headPromptShape
|
||||
) : (
|
||||
<>
|
||||
<span data-language-content="en">{headPromptShape.en}</span>
|
||||
<span data-language-content="pt" hidden>
|
||||
{headPromptShape.pt}
|
||||
</span>
|
||||
</>
|
||||
)
|
||||
}
|
||||
</span>
|
||||
</div>
|
||||
{
|
||||
routes.map((route) => (
|
||||
@@ -37,9 +87,42 @@ const { routes, initial = routes[0]?.id ?? 'plan' } = Astro.props;
|
||||
data-route={route.id}
|
||||
aria-pressed={route.id === initial}
|
||||
>
|
||||
<strong>{route.strong}</strong>
|
||||
<b>{route.profile}</b>
|
||||
<small>{route.prompt}</small>
|
||||
<strong>
|
||||
{typeof route.strong === 'string' ? (
|
||||
route.strong
|
||||
) : (
|
||||
<>
|
||||
<span data-language-content="en">{route.strong.en}</span>
|
||||
<span data-language-content="pt" hidden>
|
||||
{route.strong.pt}
|
||||
</span>
|
||||
</>
|
||||
)}
|
||||
</strong>
|
||||
<b>
|
||||
{typeof route.profile === 'string' ? (
|
||||
route.profile
|
||||
) : (
|
||||
<>
|
||||
<span data-language-content="en">{route.profile.en}</span>
|
||||
<span data-language-content="pt" hidden>
|
||||
{route.profile.pt}
|
||||
</span>
|
||||
</>
|
||||
)}
|
||||
</b>
|
||||
<small>
|
||||
{typeof route.prompt === 'string' ? (
|
||||
route.prompt
|
||||
) : (
|
||||
<>
|
||||
<span data-language-content="en">{route.prompt.en}</span>
|
||||
<span data-language-content="pt" hidden>
|
||||
{route.prompt.pt}
|
||||
</span>
|
||||
</>
|
||||
)}
|
||||
</small>
|
||||
</button>
|
||||
))
|
||||
}
|
||||
|
||||
@@ -7,24 +7,40 @@
|
||||
// paired with a `<article>` detail panel by the parent page; this component
|
||||
// renders only the picker.
|
||||
|
||||
type Localized = { en: string; pt: string };
|
||||
|
||||
interface PackageFile {
|
||||
id: 'skill' | 'references' | 'scripts' | 'assets' | string;
|
||||
/** Path rendered inside `<code>`, e.g. "SKILL.md". */
|
||||
path: string;
|
||||
/** Helper copy under the path. */
|
||||
small: string;
|
||||
small: string | Localized;
|
||||
}
|
||||
|
||||
interface Props {
|
||||
files: PackageFile[];
|
||||
initial?: string;
|
||||
packageLabel?: string | Localized;
|
||||
}
|
||||
|
||||
const { files, initial = files[0]?.id ?? 'skill' } = Astro.props;
|
||||
const { files, initial = files[0]?.id ?? 'skill', packageLabel = 'SKILL PACKAGE' } = Astro.props;
|
||||
---
|
||||
|
||||
<div class="skill-package" role="tree" aria-label="Skill package files">
|
||||
<span class="skill-package-label">SKILL PACKAGE</span>
|
||||
<span class="skill-package-label">
|
||||
{
|
||||
typeof packageLabel === 'string' ? (
|
||||
packageLabel
|
||||
) : (
|
||||
<>
|
||||
<span data-language-content="en">{packageLabel.en}</span>
|
||||
<span data-language-content="pt" hidden>
|
||||
{packageLabel.pt}
|
||||
</span>
|
||||
</>
|
||||
)
|
||||
}
|
||||
</span>
|
||||
{
|
||||
files.map((file) => (
|
||||
<button
|
||||
@@ -34,7 +50,18 @@ const { files, initial = files[0]?.id ?? 'skill' } = Astro.props;
|
||||
aria-selected={file.id === initial}
|
||||
>
|
||||
<code>{file.path}</code>
|
||||
<small>{file.small}</small>
|
||||
<small>
|
||||
{typeof file.small === 'string' ? (
|
||||
file.small
|
||||
) : (
|
||||
<>
|
||||
<span data-language-content="en">{file.small.en}</span>
|
||||
<span data-language-content="pt" hidden>
|
||||
{file.small.pt}
|
||||
</span>
|
||||
</>
|
||||
)}
|
||||
</small>
|
||||
</button>
|
||||
))
|
||||
}
|
||||
|
||||
@@ -6,15 +6,17 @@
|
||||
// the `data-tree` hook asserted by `scripts/verify.mjs`. The `root` node and
|
||||
// the `initial` branch are marked selected.
|
||||
|
||||
type Localized = { en: string; pt: string };
|
||||
|
||||
interface Branch {
|
||||
/** The `data-tree` hook, e.g. "ui", "tests", "docs". */
|
||||
id: string;
|
||||
/** Uppercase label, e.g. "UI AGENT". */
|
||||
label: string;
|
||||
label: string | Localized;
|
||||
/** Strong line, e.g. "agent/ui". */
|
||||
strong: string;
|
||||
/** Status small, e.g. "3 files · working". */
|
||||
small: string;
|
||||
small: string | Localized;
|
||||
/** CSS modifier so each branch picks up its tone. */
|
||||
tone: 'ui' | 'tests' | 'docs' | string;
|
||||
}
|
||||
@@ -22,9 +24,11 @@ interface Branch {
|
||||
interface Props {
|
||||
branches: Branch[];
|
||||
initial?: string;
|
||||
rootLabel?: string | Localized;
|
||||
rootSmall?: string | Localized;
|
||||
}
|
||||
|
||||
const { branches, initial = 'main' } = Astro.props;
|
||||
const { branches, initial = 'main', rootLabel = 'ROOT', rootSmall = '● clean' } = Astro.props;
|
||||
---
|
||||
|
||||
<div class="tree-stage" role="tree" aria-label="Repository worktree topology">
|
||||
@@ -39,8 +43,37 @@ const { branches, initial = 'main' } = Astro.props;
|
||||
data-tree="main"
|
||||
role="treeitem"
|
||||
aria-selected={initial === 'main'}
|
||||
><span>ROOT</span><strong>main</strong><small>● clean</small></button
|
||||
>
|
||||
<span>
|
||||
{
|
||||
typeof rootLabel === 'string' ? (
|
||||
rootLabel
|
||||
) : (
|
||||
<>
|
||||
<span data-language-content="en">{rootLabel.en}</span>
|
||||
<span data-language-content="pt" hidden>
|
||||
{rootLabel.pt}
|
||||
</span>
|
||||
</>
|
||||
)
|
||||
}
|
||||
</span>
|
||||
<strong>main</strong>
|
||||
<small>
|
||||
{
|
||||
typeof rootSmall === 'string' ? (
|
||||
rootSmall
|
||||
) : (
|
||||
<>
|
||||
<span data-language-content="en">{rootSmall.en}</span>
|
||||
<span data-language-content="pt" hidden>
|
||||
{rootSmall.pt}
|
||||
</span>
|
||||
</>
|
||||
)
|
||||
}
|
||||
</small>
|
||||
</button>
|
||||
{
|
||||
branches.map((branch) => (
|
||||
<button
|
||||
@@ -50,9 +83,31 @@ const { branches, initial = 'main' } = Astro.props;
|
||||
aria-selected={branch.id === initial}
|
||||
>
|
||||
<>
|
||||
<span>{branch.label}</span>
|
||||
<span>
|
||||
{typeof branch.label === 'string' ? (
|
||||
branch.label
|
||||
) : (
|
||||
<>
|
||||
<span data-language-content="en">{branch.label.en}</span>
|
||||
<span data-language-content="pt" hidden>
|
||||
{branch.label.pt}
|
||||
</span>
|
||||
</>
|
||||
)}
|
||||
</span>
|
||||
<strong>{branch.strong}</strong>
|
||||
<small>{branch.small}</small>
|
||||
<small>
|
||||
{typeof branch.small === 'string' ? (
|
||||
branch.small
|
||||
) : (
|
||||
<>
|
||||
<span data-language-content="en">{branch.small.en}</span>
|
||||
<span data-language-content="pt" hidden>
|
||||
{branch.small.pt}
|
||||
</span>
|
||||
</>
|
||||
)}
|
||||
</small>
|
||||
</>
|
||||
</button>
|
||||
))
|
||||
|
||||
@@ -10,6 +10,8 @@ const { title, description, lang = 'en' } = Astro.props;
|
||||
// Self-hosted Manrope and DM Mono. Lives in `public/fonts/` rather than the
|
||||
// bundled CSS because the legacy stylesheets @import the same file, so there
|
||||
// is exactly one copy of the faces. See public/fonts/fonts.css.
|
||||
import tokensStylesheet from '../styles/tokens.css?url';
|
||||
|
||||
const fonts = `${import.meta.env.BASE_URL}fonts/fonts.css`.replace('//', '/');
|
||||
---
|
||||
|
||||
@@ -20,6 +22,7 @@ const fonts = `${import.meta.env.BASE_URL}fonts/fonts.css`.replace('//', '/');
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>{title}</title>
|
||||
<meta name="description" content={description} />
|
||||
<link rel="stylesheet" href={tokensStylesheet} />
|
||||
<link rel="stylesheet" href={fonts} />
|
||||
<slot name="styles" />
|
||||
</head>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,2 +0,0 @@
|
||||
/* Base styles and variables imported */
|
||||
@import url('./tokens.css');
|
||||
@@ -11,6 +11,10 @@
|
||||
--red: #a7483f;
|
||||
--violet: #6b668f;
|
||||
|
||||
/* Fonts */
|
||||
--font-sans: manrope, arial, sans-serif;
|
||||
--font-mono: 'DM Mono', monospace;
|
||||
|
||||
/* Typography Scale */
|
||||
--step-display: clamp(56px, 9vw, 126px);
|
||||
--step-6: clamp(36px, 5vw, 65px);
|
||||
|
||||
+2
-2
File diff suppressed because one or more lines are too long
+70
-1
@@ -1 +1,70 @@
|
||||
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>AI For Dummies — Route map</title><link rel="stylesheet" href="../chapters.css"></head><body><main><header class="top"><a href="../full-guide/">← AI FOR DUMMIES</a><span>00 / ROUTE MAP</span><a href="../skills-review/">review desk ↗</a></header><section class="hero"><p class="eyebrow">Start here</p><h1>Ship the<br><em>system.</em></h1><p>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.</p></section><section class="grid"><article class="card"><b>01</b><h2>Models</h2><p>Capability and effort are separate knobs.</p><a href="../models/">Open chapter →</a></article><article class="card"><b>02</b><h2>Agents & trees</h2><p>Bound roles, handoffs, and worktrees.</p><a href="../agents/">Open chapter →</a></article><article class="card"><b>03</b><h2>Skills</h2><p>Capture repeatable decisions.</p><a href="../skills/">Open chapter →</a></article><article class="card"><b>04</b><h2>Rules</h2><p>Connect guidance to enforcement.</p><a href="../rules/">Open chapter →</a></article><article class="card"><b>05</b><h2>Practice</h2><p>Compare prompts and skill-enabled runs.</p><a href="../hands-on/starter/">Open lab →</a></article><article class="card"><b>06</b><h2>Review desk</h2><p>Browse original files and improved drafts.</p><a href="../skills-review/">Open desk →</a></article></section><nav class="links"><a href="../full-guide/">Full field guide</a><a href="../docs/operations-guide.md">Operations guide</a></nav><footer>Each chapter stands alone; the order follows a real task becoming a reliable change.</footer></main></body></html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1" />
|
||||
<title>AI For Dummies — Route map</title>
|
||||
<link rel="stylesheet" href="../chapters.css" />
|
||||
</head>
|
||||
<body>
|
||||
<main>
|
||||
<header class="top">
|
||||
<a href="../full-guide/">← AI FOR DUMMIES</a><span>00 / ROUTE MAP</span
|
||||
><a href="../skills-review/">review desk ↗</a>
|
||||
</header>
|
||||
<section class="hero">
|
||||
<p class="eyebrow">Start here</p>
|
||||
<h1>Ship the<br /><em>system.</em></h1>
|
||||
<p>
|
||||
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.
|
||||
</p>
|
||||
</section>
|
||||
<section class="grid">
|
||||
<article class="card">
|
||||
<b>01</b>
|
||||
<h2>Models</h2>
|
||||
<p>Capability and effort are separate knobs.</p>
|
||||
<a href="../models/">Open chapter →</a>
|
||||
</article>
|
||||
<article class="card">
|
||||
<b>02</b>
|
||||
<h2>Agents & trees</h2>
|
||||
<p>Bound roles, handoffs, and worktrees.</p>
|
||||
<a href="../agents/">Open chapter →</a>
|
||||
</article>
|
||||
<article class="card">
|
||||
<b>03</b>
|
||||
<h2>Skills</h2>
|
||||
<p>Capture repeatable decisions.</p>
|
||||
<a href="../skills/">Open chapter →</a>
|
||||
</article>
|
||||
<article class="card">
|
||||
<b>04</b>
|
||||
<h2>Rules</h2>
|
||||
<p>Connect guidance to enforcement.</p>
|
||||
<a href="../rules/">Open chapter →</a>
|
||||
</article>
|
||||
<article class="card">
|
||||
<b>05</b>
|
||||
<h2>Practice</h2>
|
||||
<p>Compare prompts and skill-enabled runs.</p>
|
||||
<a href="../hands-on/starter/">Open lab →</a>
|
||||
</article>
|
||||
<article class="card">
|
||||
<b>06</b>
|
||||
<h2>Review desk</h2>
|
||||
<p>Browse original files and improved drafts.</p>
|
||||
<a href="../skills-review/">Open desk →</a>
|
||||
</article>
|
||||
</section>
|
||||
<nav class="links">
|
||||
<a href="../full-guide/">Full field guide</a
|
||||
><a href="../docs/operations-guide.md">Operations guide</a>
|
||||
</nav>
|
||||
<footer>
|
||||
Each chapter stands alone; the order follows a real task becoming a reliable change.
|
||||
</footer>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Reference in New Issue
Block a user