completion-checklist
Positive checklist for finishing a /create-module or /add-operation task. Use right before declaring done or opening a PR.
SKILL.md.claude/skills/completion-checklist/SKILL.md
GitHubCompletion checklist
A task is done when every box below is checked. This is the positive form of @.claude/skills/failure-conditions/SKILL.md.
Spec & codegen
-
api.ymldesign final, follows the 12 critical rules -
connectionProfile.ymlfinal (connector modules only) -
connectionState.ymlfinal if the module tracks token expiry (optional otherwise) -
zbb bundleSpecexits 0 -
zbb generateexits 0 -
generated/api/manifest.jsonreflects every operationId -
hub-sdk/generated/api/index.tsis populated - No
Inline*Response/Inline*RequestBodytypes anywhere ingenerated/
Implementation
-
<Class>Implimplements the generated<Class>Connectorinterface - Connector lifecycle methods present and async:
connect,disconnect,isConnected,metadata,isSupported - One
<Tag>ProducerImplper tag inapi.yml - Mappers in
src/mappers/(orsrc/Mappers.ts) usemap()from@zerobias-org/util-hub-module-utils -
src/index.tsre-exportsgenerated/api/index.js+generated/model/index.jsand exportsnew<Class>() - All relative imports end in
.js - No
Promise<any>, noprocess.envinsrc/ -
zbb compileexits 0 -
zbb lintexits 0
Tests
-
test/unit/ConnectionTest.test.tscovers all lifecycle methods (connectors) -
test/unit/<Tag>ProducerTest.test.tsper producer, with happy + error paths - Unit tests use
import nock from 'nock'(default import) andnock.cleanAll()inafterEach -
test/e2e/constants.tsdeclares env-backed constants with sensible defaults -
test/e2e/<name>.test.tsusesdescribeModule<T>withCoreError.deserializeas the 3rd arg - Module type imported as
typefrom../../hub-sdk/generated/api/index.js - No
dotenv, notest/integration/, no nock intest/e2e/ -
zbb test --slot localexits 0 (unit) -
zbb testDirect --slot localexits 0 (e2e direct) -
zbb testDocker --slot localexits 0 (e2e docker, connectors only) - Mapper runtime validation pass green — zero missing fields per
@.claude/skills/mapper-runtime/SKILL.md
Build & gate
-
zbb gate --slot localexits 0 -
gate-stamp.jsonpresent in the module dir -
zbb gateCheckexits 0 (stamp matches current source) -
dist/src/index.js,dist/src/index.d.ts,dist/module-<name>.yml,generated/api/manifest.jsonall present - No
npm-shrinkwrap.jsonin the module dir -
package-lock.jsonpresent -
package.json.type === "module" -
package.json.zerobias.packageset - For connectors: Docker image built (part of
zbb gate)
Docs
-
README.mddocuments how to connect (credential acquisition) and at least one operation - Any non-obvious decisions (e.g. why a custom
connectionState.yml) explained in the PR description, not in code comments
Repo scope
- Only files inside
package/<vendor>/[<suite>/]<service>/(plus that path'sgate-stamp.json) were modified - No sibling-module files touched
- Branch is a feature branch (not
main) - Commit message follows conventional commits
- PR description summarizes what's in the module + how to test
Completion signal
When all boxes check, the right summary is one or two lines:
Gates 1–6 green.
gate-stamp.jsonwritten and staged. Ready to commit.
Validation script
#!/usr/bin/env bash
set -u
cd "$1" || exit 1 # pass the module dir as first arg
fail=0
note=$(printf '\033[33m')
err=$(printf '\033[31m')
ok=$(printf '\033[32m')
rst=$(printf '\033[0m')
# Spec
grep -E "describe[A-Z]|nullable:|'40[0-9]'|'50[0-9]'" api.yml \
&& { echo "${err}✗ forbidden tokens in api.yml${rst}"; fail=1; }
# package.json shape
[ "$(jq -r .type package.json)" = "module" ] || { echo "${err}✗ package.json missing type=module${rst}"; fail=1; }
jq -e '.zerobias.package' package.json >/dev/null || { echo "${err}✗ package.json missing zerobias.package${rst}"; fail=1; }
[ -f npm-shrinkwrap.json ] && { echo "${err}✗ npm-shrinkwrap.json present${rst}"; fail=1; }
# src/
grep -rn "Promise<any>" src/ \
&& { echo "${err}✗ Promise<any> in src/${rst}"; fail=1; }
grep -rn "process\.env" src/ \
&& { echo "${err}✗ process.env in src/${rst}"; fail=1; }
grep -rnE "from '\.\.?\/[^']*'" src/ test/ | grep -v "\.js'" \
&& { echo "${err}✗ relative imports missing .js${rst}"; fail=1; }
# Tests
grep -rn "import \* as nock" test/unit/ \
&& { echo "${err}✗ wildcard nock import${rst}"; fail=1; }
grep -rnE "jest\.mock|from 'sinon'|fetch-mock|from 'msw'" test/ \
&& { echo "${err}✗ forbidden mock library${rst}"; fail=1; }
[ -d test/integration ] \
&& { echo "${err}✗ test/integration/ exists (use test/e2e/)${rst}"; fail=1; }
grep -rn "process\.env" test/e2e/ 2>/dev/null | grep -v "/constants.ts:" \
&& { echo "${err}✗ process.env outside constants.ts${rst}"; fail=1; }
grep -rn "from 'dotenv'" . --include='*.ts' --include='*.json' 2>/dev/null \
&& { echo "${err}✗ dotenv import${rst}"; fail=1; }
# Build outputs (require zbb gate to have been run)
[ -f gate-stamp.json ] || { echo "${err}✗ gate-stamp.json missing — run zbb gate --slot local${rst}"; fail=1; }
[ -f dist/src/index.js ] || { echo "${note}note: dist/ not present — run zbb gate first${rst}"; }
[ -f generated/api/manifest.json ] || { echo "${note}note: generated/ not present — run zbb generate first${rst}"; }
[ $fail -eq 0 ] && echo "${ok}✓ static checks pass${rst}"
exit $fail
Related
- @.claude/skills/failure-conditions/SKILL.md — the negative form
- @.claude/skills/gate-build/SKILL.md — Gate 6 (last step)
- @.claude/skills/production-readiness/SKILL.md — extra checks before publishing