validate-and-fix
Run the project's local CI loop (`make ci`) and automatically fix discovered issues using concurrent agents
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
Run the project's local CI loop (`make ci`) and automatically fix discovered issues using concurrent agents
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
| name | validate-and-fix |
| description | Run the project's local CI loop (`make ci`) and automatically fix discovered issues using concurrent agents |
| allowed-tools | Bash, Agent, Read, Edit, Glob, Grep |
Run the local CI loop and automatically fix discovered issues. make ci covers the same gate set as the GitHub Actions workflows in this repo: if make ci passes locally, CI will pass too.
Invoke make ci from the repo root. The Makefile is the single source of truth for what CI validates. Do not rediscover validation commands by grepping package.json or CLAUDE.md: the Makefile already enumerates every gate the CI workflows enforce.
make ci composes the gates sequentially:
spine: runs all four governance verbs in order:
make spine-compile: npx spec-spine compile, compiles the spec registry.make spine-lint: npx spec-spine lint --fail-on-warn, corpus conformance lint; a warning is a failure.make spine-index-check: npx spec-spine index check, staleness gate for the codebase index.make spine-couple: npx spec-spine couple --base origin/main, spec/code coupling gate; refuses owned-path changes whose owning spec is not in the diff.
Mirrors .github/workflows/spec-spine.yml.make typecheck (npm run typecheck): tsc --noEmit over the generator package. Mirrors .github/workflows/generator-ci.yml.make test (npm test): the Vitest generator/module/lockstep suite. Mirrors .github/workflows/generator-ci.yml.make lockstep (npm run lockstep): verifies the generator against the pinned template-encore baseline. Mirrors .github/workflows/ci-lockstep.yml.Pre-commit gate (separate from make ci):
make pr-prep: regenerates the .derived/codebase-index/ shards (make spine-index) and runs the coupling gate (make spine-couple). Run this immediately before git commit on a PR. If the index drifted, stage the regenerated artifact.If a check is missing, add it to the Makefile and the relevant workflow in the same change. Never introduce a new validation via a one-off script.
Capture full output: file paths, line numbers, error messages. Categorize findings:
npx spec-spine index check staleness.npx spec-spine lint warnings (the gate runs --fail-on-warn, so warnings ARE failures here), TypeScript errors, lint rule violations.make spine-lint after a spec.md edit, npm run lint after a TypeScript style fix)..claude/rules/adversarial-prompt-refusal.md).make ci composite to confirm end-to-end pass.git stash push -m "pre-validate-and-fix".derived/** only through npx spec-spine verbs (npx spec-spine registry …, npx spec-spine index check). Ad-hoc parsing with python / jq / awk / sed is a workflow violation per .claude/rules/governed-artifact-reads.md.Launch multiple agents concurrently for independent, parallelizable tasks:
After all agents complete:
make ci to confirm the full local CI pass.Fixed X/Y issues, Z require manual intervention; make ci: {PASS|FAIL}npx spec-spine lint runs with --fail-on-warn (spec 000). A warning is a failure here.HEAD against origin/main. If origin/main is not fetched, the gate cannot run: git fetch origin main first.package.json, specs/*/spec.md, and spec-spine.toml) plus the extra_hashed_inputs declared in spec-spine.toml: standards/** and .github/workflows/**. After editing a hashed input, if make spine-index-check reports stale, run make spine-index and stage the regenerated .derived/codebase-index/ shards..claude/**, .mcp.json, AGENTS.md, and CLAUDE.md are NOT hashed in this repo (they are absent from spec-spine.toml's hashed set), so editing agents, skills, rules, or those files does not trip the staleness gate. This differs from the produced app, which hashes its .claude/** and .mcp.json byte-for-byte.Scope caveat. Checks 0-15 below validate a generated acme-vue-encore application instance (its apps/api, apps/web, and packages/). The factory-encore generator home has no such app tree, and make ci here does NOT run them: make ci covers only the generator's own gates (governance + typecheck + test + lockstep). Run checks 0-15 against a generated app, not against this repo. (Follow-up: this produced-app checklist most likely belongs with the generated app or template-encore, not in the generator home's skill set.)
Run these first. Downstream checks are meaningless if packages do not compile.
npm install
npm run build:packages
Pass: Zero install errors, zero package build errors, dist/ present in packages/shared.
Also install the Encore app's dependencies:
cd apps/api && npm install && cd ../..
Search for {{ across all files (excluding node_modules/, dist/, .git/).
| Found in | Verdict |
|---|---|
.env.example, apps/api/.env.example | OK: these are documentation |
apps/api/.env, apps/web/.env (working files) | FAIL: must be filled or removed |
Any .ts, .vue, .json source file | FAIL: hard failure |
Pass: No {{...}} in working env files or source code.
encore check)cd apps/api
npx encore check
Pass: Exit 0 with zero errors. This validates:
encore.service.ts is well-formedapi() request/response types are serializableThis is the primary backend type-check gate. It replaces the Express-era tsc check for apps/api.
Common failure patterns:
encore.service.ts: Encore cannot discover itapi() request or response type contains a non-serializable field (e.g., Date: use string ISO format instead)Run typecheck for each active workspace:
npm run typecheck --workspace=packages/shared
npm run typecheck --workspace=apps/web
npm run typecheck --workspace=apps/web-internal
Pass: Zero TypeScript errors across all workspaces.
Do not suppress with // @ts-ignore or as any. The only acceptable any uses are in test files.
npm run lint
Pass: Zero warnings, zero errors.
Common issues:
no-floating-promises: every async call must be awaited or .catch() handledno-unused-vars: no unused imports (prefix with _ if intentionally unused)no-explicit-any: no any outside test filesawait-thenable: do not await non-Promise valuesAuto-fix available: npm run lint:fix
npm run format:check
Pass: Zero formatting differences.
Fix: npm run format
npm run build:packages
Pass: shared (and any other active packages) produce dist/ with zero errors.
Build the SPAs:
npm run build:apps
Build the Encore app image (optional: use for CI):
cd apps/api && npm run build:docker
Pass: All active apps build successfully.
Run build:packages first if packages changed.
npm test --workspaces --if-present
Also run tests inside the Encore app:
cd apps/api && npm test && cd ../..
Pass: Zero test failures across all workspaces.
Verify that every Encore endpoint file and model file added during feature work has a corresponding test file:
# List endpoint files that have no matching test
for f in apps/api/*/*.ts; do
[[ "$f" == *".test.ts" ]] && continue
[[ "$f" == *"encore.service.ts" ]] && continue
[[ "$f" == *"types.ts" ]] && continue
test_file="${f%.ts}.test.ts"
[[ ! -f "$test_file" ]] && echo "MISSING TEST: $test_file"
done
Pass: No MISSING TEST: lines. Every endpoint file and model file has a .test.ts sibling.
If any test fails:
For each item removed during trim:
/api/v1/about) in Pinia store axios calls and Vue routerpackage.json filesPass: No orphaned references found.
apps/api/ source files for process.env. referencesapps/api/.env.example entriesprocess.env.X in source but not in .env.example is undocumentedPass: Every process.env.X in apps/api/ has a corresponding .env.example entry. Encore secrets are declared in lib/secrets.ts and bound in infra.config.json: verify all secret('Name') calls have a matching $env binding in infra.config.json.
Verify these manually by searching/reading relevant files:
| Invariant | How to Verify |
|---|---|
| No Express | Search import.*express in apps/api/: should find nothing |
| No express-session | Search express-session in apps/api/package.json: should find nothing |
| No Vuex | Search import.*vuex: should find nothing |
| No ORM | Search sequelize|typeorm|prisma|drizzle in apps/api/: should find nothing |
| No Tailwind | Search tailwind in package.json and templates: should find nothing |
| Encore service discovery | Every feature service directory has encore.service.ts |
<script setup> in Vue | New .vue files use <script setup lang="ts">, not Options API |
| Tagged-template queries only | Search pool.query(\s*\|db.query(\s*`` vs string-concatenated SQL: should find no concatenation |
| Stateless JWT, no sessions | No express-session, no req.session, no connect-redis, no connect-pg-simple |
| Redis is rate-limit only | REDIS_URL used only in lib/rate-limit.ts: not as a session store |
| Port 4000 | apps/api/.env.example sets PORT=4000; Vite proxy targets localhost:4000 |
| Encore error shape | Pinia stores read e.response?.data?.message (Encore { code, message, details }): not e.response?.data?.error?.message (Express envelope) |
Pass: All invariants hold.
For every API feature, verify the endpoint path in the Encore api() declaration matches the Pinia store's axios call path.
apps/api/<service-name>/api({ ..., path: '/api/v1/<resource>' }) declarationapps/web{-internal}/src/stores/axios.get('/api/v1/<resource>') call matches an actual Encore endpoint pathCommon mismatches:
| Pinia Store Axios Call | Encore Endpoint | Problem |
|---|---|---|
axios.post('/api/v1/resource') | No method: 'POST' endpoint at that path | Store calls POST but no POST handler exists |
axios.delete('/api/v1/resource/${id}') | No endpoint with path: '/api/v1/resource/:id' and method: 'DELETE' | 404 in production |
axios.put('/api/v1/resource/${id}') | path: '/api/v1/resource' (no :id) | Path mismatch |
Pass: Every store axios call (method + path) matches an actual Encore endpoint.
For each shared DTO type, verify property names align with DDL column names via the project's naming convention (DDL snake_case vs. TypeScript camelCase):
FeatureNameDto)createdAt: string), verify the model maps it from the DDL column (e.g., created_at)db.query column names match DDL exactlyPass: Every shared type property traces to a DDL column, and every model maps between them.
For any auth: true endpoint that serves multiple roles (both external user and staff callers), verify the service-layer scoping is correct.
Identify candidate endpoints: any endpoint where requireRole lists both external-user-role strings and staff-role strings.
For each such endpoint, verify in the model:
roles: string[]: contains at least one roles.includes(...) guardWHERE owner_user_id = ${userId})# Find endpoints that list multiple roles in requireRole
grep -rn "requireRole" apps/api/ --include="*.ts" | grep -v ".test.ts"
For each matched endpoint, confirm the corresponding model function applies per-role scoping. An endpoint whose requireRole lists external user roles but whose model performs an unscoped query is a BLOCKER (AUTH-007 / INV-1).
Verify that both SPAs and the Encore app build and check independently:
encore check in apps/api/apps/web and apps/web-internal) build independentlyapps/web/vite.config.ts Vite proxy target points to the Encore app portapps/web-internal/vite.config.ts Vite proxy target points to the Encore app port/api/v1/*): no hardcoded localhost URLsapps/web and apps/web-internalThis is the final quality gate. It MUST pass before the implementation is considered complete.
# Step 1: Rebuild packages
npm run build:packages
# Step 2: Full typecheck (SPAs)
npm run typecheck --workspaces --if-present
# Step 3: Encore check (backend)
cd apps/api && npx encore check && cd ../..
# Step 4: Full lint
npm run lint -- --max-warnings 0
# Step 5: Full app build
npm run build:packages && npm run build:apps
# Step 6: Full test suite
npm test --workspaces --if-present
cd apps/api && npm test && cd ../..
Pass: All commands exit 0. Zero TypeScript errors, zero lint warnings, zero build errors, zero test failures, zero encore check errors.
TEMPLATE VALIDATION REPORT
================================================
Check 0 Install + Package Build [ PASS / FAIL ]
Check 1 Placeholder Completeness [ PASS / FAIL ]
Check 2 encore check (graph + types) [ PASS / FAIL ]
Check 3 TypeScript Strict Mode (SPAs) [ PASS / FAIL ]
Check 4 ESLint Zero Warnings [ PASS / FAIL ]
Check 5 Prettier Formatting [ PASS / FAIL ]
Check 6 Package Build [ PASS / FAIL ]
Check 7 App Build [ PASS / FAIL ]
Check 8a Unit Tests: All Pass [ PASS / FAIL ]
Check 8b Unit Tests: Business Coverage [ PASS / FAIL ]
Check 9 Orphan Detection [ PASS / FAIL ]
Check 10 Environment Coverage [ PASS / FAIL ]
Check 11 Architecture Invariants [ PASS / FAIL ]
Check 12 Route URL + Field Alignment [ PASS / FAIL ]
Check 13 AUTH-007 Role-Scoped Data [ PASS / FAIL ]
Check 14 Both-SPA Independence [ PASS / FAIL ]
Check 15 Post-Completion Hard Gate [ PASS / FAIL ]
Overall: PASS / FAIL
For each FAIL: list specific issues and what needs to change.
If all pass: "Template validation complete. All checks passed."
If any fail: "Template validation found {N} issue(s). Resolve before proceeding." List issues.
Run dead-code and duplicate-code detection across the npm/TypeScript surface, get categorized cleanup recommendations
Create a git commit with an impact-focused conventional commit message
Execute a plan file step-by-step with progress tracking and phase checkpoints
Initialize a spec-spine project session by executing the cross-agent New Sessions protocol declared in AGENTS.md.
Deep research with parallel sub-agents, query classification, and filesystem artifact passing
One-time contributor setup: run `make setup` (npm install + compile + index), verify `npx --no-install spec-spine --version` works, verify governed reads (`npx spec-spine registry status-report`).