diff --git a/docs/operations-guide.md b/docs/operations-guide.md index 80e62bc..326131f 100644 --- a/docs/operations-guide.md +++ b/docs/operations-guide.md @@ -384,10 +384,10 @@ Compare: ### Hands-on rules lab A second lab at `hands-on/rules/` mirrors the starter's visual system and runs -the same exercise against rule sources instead of feature work. It lists five -toggleable rule sources — `AGENTS.md`, the `gate-discipline` skill body, the -Husky `pre-commit` hook, the `check-ui-contract.mjs` enforcer, and -`commitlint` — and rebuilds the **ruled** prompt live as each toggle flips. +the same exercise against rule sources. It lists five toggleable rule sources +— `AGENTS.md`, the `gate-discipline` skill body, the Husky `pre-commit` hook, +the `check-ui-contract.mjs` enforcer, and `commitlint` — and rebuilds the +**ruled** prompt live as each toggle flips. Run it: @@ -397,9 +397,8 @@ python3 -m http.server 4173 Open [http://localhost:4173/hands-on/rules/](http://localhost:4173/hands-on/rules/). Compare the **naive** and **ruled** prompt panels. Toggle rules off to shrink -the prompt; toggle them on to widen the leash. Copy the final prompt and run -it against a real coding agent — the lab is deliberately short so the spend -stays bounded. +the prompt; toggle them on to add more guards. Copy the final prompt and run +it against a real coding agent. ## Rules and enforcement case study diff --git a/hands-on/rules/README.md b/hands-on/rules/README.md index fac31d9..d5cc0e2 100644 --- a/hands-on/rules/README.md +++ b/hands-on/rules/README.md @@ -21,7 +21,7 @@ Open `index.html` directly. No build, no server, no `npm install`. ## Mirror of `/hands-on/starter` -Same visual system (`--paper`, `--ink`, `--blue`, `--gold`), same vanilla JS pattern, same single-file layout. Drop-in alongside the starter page under `hands-on/rules/`. +Same visual system as the starter (`--paper`, `--ink`, `--blue`, `--gold`). Drop-in replacement under `hands-on/rules/`. ## Token budget diff --git a/hands-on/rules/index.html b/hands-on/rules/index.html index 05b6a1f..8d3976f 100644 --- a/hands-on/rules/index.html +++ b/hands-on/rules/index.html @@ -10,7 +10,7 @@
HANDS-ON / RULES

Guardrails

-

Toggle rules. Watch the prompt change. Same task, different leash.

+

Toggle rules. Same task, different coverage.

@@ -27,7 +27,7 @@
-
NAIVE

Vanilla ask

+
NAIVE

Plain prompt


         
diff --git a/index.html b/index.html index 958bdb3..1fbb68a 100644 --- a/index.html +++ b/index.html @@ -25,12 +25,12 @@

Skills

Write the right way
once.

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 clearly02 / load detail on demand03 / return evidence
SKILL PACKAGE
name: review-ui · check focus, mobile, reduced motion · run verification · return evidence

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.

AFTER REAL USE
observe failuresharpen one ruleretest behaviorkeep it narrow

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.

ONE PRACTICAL LOADOUT
PLAN unlazy BUILD ponytail-lite DEBUG diagnosing-bugs REPORT caveman
INSTALL PACKAsk your coding agent to verify, install, and validate the skills.
Review every source before installation. Existing local skills must be preserved.
-

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.

THE MISSING FEATUREAdd All / Open / Done filters that survive reload and browser navigation.
STACK HTML · CSS · JavaScript DEPENDENCIES none FILES 3
RUN AGood prompt
Clear context · constraints · acceptance · evidence
RUN BGood prompt + skills
Same contract · explicit working methods · stronger proof
COMPARE THE RUNS
01 Files changed
02 New dependencies
03 Checks actually run
04 Evidence returned

+

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.

THE MISSING FEATUREAdd All / Open / Done filters that survive reload and browser navigation.
STACK HTML · CSS · JavaScript DEPENDENCIES none FILES 3
RUN AGood prompt
Clear context · constraints · acceptance · evidence
RUN BGood prompt + skills
Same contract · explicit working methods · stronger proof
COMPARE THE RUNS
01 Files changed
02 New dependencies
03 Checks actually run
04 Evidence returned

-

From confident drift to decisive proof

Three layers.
Run each separately.

Every gate needs its own line, its own exit code, and its own evidence. The matrix below is the deliverable — not opinion, not prose, not "looks done".

01 · STATIC

Shape and types

Format, lint, type-check. Fast and scope-bounded. Run on every save.

pnpm lint; echo "lint=$?" -pnpm typecheck; echo "typecheck=$?"
02 · BEHAVIOR

Deterministic proof

Unit and contract tests. Repeatable. Run before claiming done.

pnpm test; echo "test=$?" -cd services/api && go test ./...
03 · INTEGRATION

Real surface, real load

Drive the actual UI, API, browser. Slow, fragile, decisive. Only this catches mobile overflow and missing 404.

pnpm check:ui; echo "ui=$?" -TURBO_FORCE=true pnpm e2e
FOUR WAYS GREEN 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

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

Static + unit can both be green while the page breaks on mobile or the API never returns 404.

+

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.

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.

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

Go deeper with official documentation, production case studies, Medium, and practitioner workflows. Rules and enforcement case study → Primary references → 12-part reading path →

diff --git a/responsive.css b/responsive.css index 8906e89..92ae71b 100644 --- a/responsive.css +++ b/responsive.css @@ -65,7 +65,7 @@ button{font-family:inherit} .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} /* 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:6px 24px;margin-top:18px}.starter-links .starter-link{margin-top:0} +.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} diff --git a/scripts/verify.mjs b/scripts/verify.mjs index 1364cf8..d79f796 100644 --- a/scripts/verify.mjs +++ b/scripts/verify.mjs @@ -8,6 +8,9 @@ const starterHtml = read('hands-on/starter/index.html'); const starterJs = read('hands-on/starter/app.js'); const skillSources = read('docs/references/skill-sources.md'); const modelRouting = read('docs/references/model-routing.md'); +const rulesHtml = read('rules/index.html'); +const rulesJs = read('rules/app.js'); +const rulesCss = read('rules/styles.css'); 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"',']+(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}`); +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}`); +console.log('rules interaction verification passed'); +if (!html.includes('href="rules/"')) throw new Error('main presentation does not link to rules page'); +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');