aidokitwiki

The Dogfood Gate

Audience-Contributor Status-Shipped v0.5

Purpose #

Explain the byte-compare invariant: from Phase 8 onward, @aidokit/adapter-claude-code must emit a .claude/ tree byte-identical to this repo's hand-built .claude/. It is the strongest integration test we have.

Big Picture #

Source: .docs/ARCHITECTURE.md §20 and CLAUDE.md §10.

The bootstrap problem: aidokit cannot use aidokit init to set up the aidokit repo until aidokit init works. So Phases 0–7 are hand-built. End of Phase 7, the maintainer runs:

mkdir aidokit-dogfood && cd aidokit-dogfood
git init
npx ../aidokit init --adapter claude-code --stack node-ts
diff -r ../aidokit/.claude  ./.claude

The diff must be empty (or only contain documented intentional differences). From Phase 8 onward, this becomes a permanent CI gate. Every change to @aidokit/adapter-claude-code that diverges from the hand-built reference is a failure to keep the dogfood diff clean.

How It Works #

Why it works as a test #

aidokit's reason to exist is "scaffold a working workflow." This repo is a working workflow. If the adapter cannot reproduce it byte-for-byte, the adapter is broken — regardless of what unit tests say. The whole class of "looks correct in tests but emits wrong in practice" failures is caught by this single diff.

What the reference is #

The hand-built .claude/ at the root of this repo. As of v1.0-rc, that directory holds the seven roles, three slash commands, 19 hook scripts, five output styles, eight schemas, and 18+ base skills exactly as documented in .docs/context/claude-workflow-kit-v4-base-part-3.md.

The v4 base parts plus the on-disk .claude/ are the reference. The adapter's job is to emit a tree that matches.

Fail-loud byte compare #

Per tie up loose ends commit 8330fde, the byte-compare is fail-loud — any difference fails the build. Documented intentional differences (e.g. {{projectName}} interpolation differences when the dogfood project's name differs from aidokit) are handled by parameterising the compare.

What is NOT covered by the gate #

Where the gate fits in CI #

The integration test that runs the byte-compare lives in packages/cli/test/integration/init-emit.test.ts (today asserts on structure; the literal byte-compare against the reference snapshot lands when the reference is generated from a verified build — see CHANGELOG.md [0.1.0-alpha]).

When the test fails, the failure surfaces the path and kind of divergence (template-updated vs user-modified vs missing); the contributor regenerates the reference if the divergence is intentional, or fixes the adapter if it is not.

Example #

A contributor adds a new built-in skill to @aidokit/base-skills:

  1. Update packages/base-skills/src/files/skills/<id>.md + src/skills.ts.
  2. pnpm build regenerates dist/files/.
  3. pnpm test runs the integration test; the emitted tree now has an extra skill file.
  4. The dogfood compare fails because the hand-built .claude/skills/ doesn't have the new skill.
  5. The contributor hand-adds the skill to the repo's .claude/skills/<id>/SKILL.md.
  6. The compare passes.

Both directions are kept in sync deliberately. The hand-built .claude/ is the source of truth; the adapter must emit it.

Diagram #

See diagrams/dogfood-loop.md.

%%{init: {
  "theme": "base",
  "themeVariables": {
    "fontFamily": "ui-sans-serif, system-ui, -apple-system, Segoe UI, sans-serif",
    "fontSize": "14px",
    "primaryColor": "#eff6ff",
    "primaryTextColor": "#0f172a",
    "primaryBorderColor": "#2563eb",
    "lineColor": "#475569",
    "secondaryColor": "#f1f5f9",
    "tertiaryColor": "#ffffff",
    "clusterBkg": "#f8fafc",
    "clusterBorder": "#cbd5e1"
  }
}}%%
flowchart LR
  classDef actor    fill:#ede9fe,stroke:#6d28d9,color:#1e1b4b,stroke-width:1.2px;
  classDef cli      fill:#dbeafe,stroke:#1d4ed8,color:#0c1f4a,stroke-width:1.4px;
  classDef adapter  fill:#cffafe,stroke:#0e7490,color:#083344;
  classDef pack     fill:#dcfce7,stroke:#15803d,color:#052e16;
  classDef core     fill:#fef9c3,stroke:#a16207,color:#422006;
  classDef artifact fill:#f1f5f9,stroke:#475569,color:#0f172a;
  classDef stop     fill:#fee2e2,stroke:#b91c1c,color:#7f1d1d,stroke-dasharray:4 3;
  classDef ok       fill:#ecfdf5,stroke:#047857,color:#064e3b;
  classDef external fill:#fff7ed,stroke:#c2410c,color:#431407;

  src["packages/adapter-claude-code/src/files/"]:::adapter
  bs["packages/base-skills/src/files/"]:::core
  cli["@aidokit/cli init (in temp dir)"]:::cli
  emitted["temp/.claude/"]:::artifact
  hand["aidokit/.claude/ (hand-built reference)"]:::artifact
  diff{{"diff -r ../.claude ./.claude"}}:::stop

  src --> cli
  bs --> cli
  cli --> emitted
  hand --> diff
  emitted --> diff
  diff -->|empty| pass["✔ dogfood clean"]:::ok
  diff -->|non-empty| fail["✘ CI fails
fix adapter OR hand-built"]:::stop

Common Mistakes #

Checklist before merging a change to @aidokit/adapter-claude-code or @aidokit/base-skills #