crewforth 0.0.1 → 3.0.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +3784 -0
- package/LICENSE +21 -0
- package/README.md +37 -7
- package/VERSION +1 -0
- package/adopt.sh +1670 -0
- package/bin/cli.js +497 -0
- package/kit/AGENT_TEMPLATE.md +92 -0
- package/kit/CLAUDE.md +228 -0
- package/kit/README.md +107 -0
- package/kit/agents/crew-backend-expert.md +95 -0
- package/kit/agents/crew-commit-agent.md +96 -0
- package/kit/agents/crew-database-expert.md +84 -0
- package/kit/agents/crew-devops-expert.md +82 -0
- package/kit/agents/crew-frontend-expert.md +85 -0
- package/kit/agents/crew-performance-expert.md +78 -0
- package/kit/agents/crew-planner.md +60 -0
- package/kit/agents/crew-privacy-agent.md +71 -0
- package/kit/agents/crew-review-agent.md +95 -0
- package/kit/agents/crew-security-expert.md +73 -0
- package/kit/agents/crew-session-manager.md +77 -0
- package/kit/agents/crew-test-expert.md +64 -0
- package/kit/eval/doctor.sh +465 -0
- package/kit/eval/gate-report.sh +137 -0
- package/kit/eval/golden-holdout.txt +53 -0
- package/kit/eval/golden-routing.txt +199 -0
- package/kit/eval/lib/crew-env.sh +14 -0
- package/kit/eval/lib/settings-json.awk +154 -0
- package/kit/eval/lib/star.sh +70 -0
- package/kit/eval/parser-conformance.sh +612 -0
- package/kit/eval/preflight.sh +186 -0
- package/kit/eval/routing-eval.sh +209 -0
- package/kit/eval/scan-skill.sh +162 -0
- package/kit/eval/smoke-test.sh +6693 -0
- package/kit/eval/update-guard.sh +81 -0
- package/kit/eval/utilization.sh +130 -0
- package/kit/hooks/board-sync.sh +106 -0
- package/kit/hooks/board.sh +962 -0
- package/kit/hooks/commit-msg +49 -0
- package/kit/hooks/context-usage.sh +353 -0
- package/kit/hooks/floor-blocklist.txt +124 -0
- package/kit/hooks/guard-bash.sh +1431 -0
- package/kit/hooks/guard-commit-scan.sh +511 -0
- package/kit/hooks/guard-write.sh +513 -0
- package/kit/hooks/pre-commit +577 -0
- package/kit/hooks/route-hint.sh +185 -0
- package/kit/hooks/secret-blocklist.txt +82 -0
- package/kit/hooks/session-guard.sh +149 -0
- package/kit/hooks/session-rehydrate.sh +41 -0
- package/kit/hooks/session-stats.sh +252 -0
- package/kit/hooks/session-update-check.sh +236 -0
- package/kit/hooks/skill-trust.sh +150 -0
- package/kit/hooks/trace-blocklist.txt +53 -0
- package/kit/settings.json +132 -0
- package/kit/skills/a11y/SKILL.md +44 -0
- package/kit/skills/adr/SKILL.md +74 -0
- package/kit/skills/api-design/SKILL.md +50 -0
- package/kit/skills/automode-policy/SKILL.md +91 -0
- package/kit/skills/automode-policy/references/policy.json +13 -0
- package/kit/skills/automode-policy/scripts/apply.sh +84 -0
- package/kit/skills/automode-policy/scripts/check.sh +102 -0
- package/kit/skills/backend-architecture/SKILL.md +103 -0
- package/kit/skills/brainstorm/SKILL.md +47 -0
- package/kit/skills/ci-pipeline/SKILL.md +38 -0
- package/kit/skills/commit-message/SKILL.md +82 -0
- package/kit/skills/commit-message/references/examples.md +8 -0
- package/kit/skills/confidence-check/SKILL.md +86 -0
- package/kit/skills/crew-board/SKILL.md +55 -0
- package/kit/skills/crew-brainstorm/SKILL.md +19 -0
- package/kit/skills/crew-code-review/SKILL.md +151 -0
- package/kit/skills/crew-code-review/references/history-search.md +19 -0
- package/kit/skills/crew-code-review/references/panel-mode.md +32 -0
- package/kit/skills/crew-code-review/references/receiving.md +23 -0
- package/kit/skills/crew-doctor/SKILL.md +36 -0
- package/kit/skills/crew-gates/SKILL.md +25 -0
- package/kit/skills/crew-handoff/SKILL.md +14 -0
- package/kit/skills/crew-plan/SKILL.md +18 -0
- package/kit/skills/crew-review/SKILL.md +23 -0
- package/kit/skills/crew-ship/SKILL.md +19 -0
- package/kit/skills/crew-skill/SKILL.md +61 -0
- package/kit/skills/crew-studio/SKILL.md +129 -0
- package/kit/skills/crew-update/SKILL.md +43 -0
- package/kit/skills/db-migration/SKILL.md +120 -0
- package/kit/skills/db-migration/references/backup-restore.md +33 -0
- package/kit/skills/db-migration/references/raw-sql.md +30 -0
- package/kit/skills/db-migration/references/tool-matrix.md +35 -0
- package/kit/skills/dependency-audit/SKILL.md +61 -0
- package/kit/skills/dependency-upgrade/SKILL.md +82 -0
- package/kit/skills/deploy/SKILL.md +100 -0
- package/kit/skills/deploy/references/proxy-ssl.md +56 -0
- package/kit/skills/deploy/references/rollback.md +18 -0
- package/kit/skills/deploy/references/scripts.md +9 -0
- package/kit/skills/deploy/references/topology-a.md +128 -0
- package/kit/skills/deploy/references/topology-b.md +44 -0
- package/kit/skills/docs-writer/SKILL.md +53 -0
- package/kit/skills/docs-writer/references/coauthoring.md +34 -0
- package/kit/skills/eval-grader/SKILL.md +75 -0
- package/kit/skills/eval-grader/references/method.md +51 -0
- package/kit/skills/frontend/SKILL.md +56 -0
- package/kit/skills/frontend/references/verify-contract.md +41 -0
- package/kit/skills/frontend-design/SKILL.md +71 -0
- package/kit/skills/frontend-design/references/design-review.md +34 -0
- package/kit/skills/frontend-rn-expo/SKILL.md +25 -0
- package/kit/skills/handoff/SKILL.md +71 -0
- package/kit/skills/handoff/references/cold-reader.md +51 -0
- package/kit/skills/i18n-integrity/SKILL.md +31 -0
- package/kit/skills/incident-runbook/SKILL.md +40 -0
- package/kit/skills/incident-runbook/references/postmortem.md +16 -0
- package/kit/skills/iterate/SKILL.md +40 -0
- package/kit/skills/mcp-builder/SKILL.md +54 -0
- package/kit/skills/mcp-builder/references/building.md +71 -0
- package/kit/skills/observability/SKILL.md +50 -0
- package/kit/skills/performance/SKILL.md +38 -0
- package/kit/skills/performance/references/bottlenecks.md +10 -0
- package/kit/skills/privacy-compliance/SKILL.md +75 -0
- package/kit/skills/red-team/SKILL.md +48 -0
- package/kit/skills/reflect/SKILL.md +57 -0
- package/kit/skills/release/SKILL.md +44 -0
- package/kit/skills/security-scan/SKILL.md +99 -0
- package/kit/skills/security-scan/references/ai-agents.md +107 -0
- package/kit/skills/security-scan/references/fronts.md +99 -0
- package/kit/skills/security-scan/references/prompting.md +23 -0
- package/kit/skills/security-scan/references/reporting.md +75 -0
- package/kit/skills/security-scan/references/verify.md +131 -0
- package/kit/skills/sonarqube-check/SKILL.md +108 -0
- package/kit/skills/sonarqube-check/references/local-engines.md +32 -0
- package/kit/skills/sonarqube-check/references/stand-up-server.md +25 -0
- package/kit/skills/spec-planning/SKILL.md +92 -0
- package/kit/skills/systematic-debugging/SKILL.md +57 -0
- package/kit/skills/systematic-debugging/references/techniques.md +44 -0
- package/kit/skills/teamboard/SKILL.md +88 -0
- package/kit/skills/teamboard/references/setup.md +37 -0
- package/kit/skills/testing/SKILL.md +49 -0
- package/kit/skills/testing/references/flaky-triage.md +51 -0
- package/kit/skills/threat-model/SKILL.md +57 -0
- package/kit/skills/threat-model/references/interview.md +51 -0
- package/kit/skills/threat-model/references/schema.md +42 -0
- package/kit/skills/token-budget/SKILL.md +51 -0
- package/kit/skills/trace-scan/SKILL.md +43 -0
- package/kit/skills/worktree/SKILL.md +40 -0
- package/kit/studio/README.md +266 -0
- package/kit/studio/ensure-node.sh +471 -0
- package/kit/studio/package.json +14 -0
- package/kit/studio/server/hooks/studio-gate.sh +169 -0
- package/kit/studio/server/index.js +902 -0
- package/kit/studio/server/lib/crew-env.js +11 -0
- package/kit/studio/server/lib/fleet.js +146 -0
- package/kit/studio/server/lib/graph.js +533 -0
- package/kit/studio/server/lib/instance.js +135 -0
- package/kit/studio/server/lib/kit-telemetry.js +182 -0
- package/kit/studio/server/lib/kit.js +158 -0
- package/kit/studio/server/lib/palette.js +118 -0
- package/kit/studio/server/lib/peers.js +72 -0
- package/kit/studio/server/lib/permissions.js +150 -0
- package/kit/studio/server/lib/projects.js +294 -0
- package/kit/studio/server/lib/roster.js +191 -0
- package/kit/studio/server/lib/session.js +309 -0
- package/kit/studio/server/lib/terminal.js +91 -0
- package/kit/studio/server/lib/transcript.js +100 -0
- package/kit/studio/web/app.js +1098 -0
- package/kit/studio/web/canvas.js +1179 -0
- package/kit/studio/web/chat.js +543 -0
- package/kit/studio/web/index.html +86 -0
- package/kit/studio/web/md.js +110 -0
- package/kit/studio/web/storage-migrate.js +23 -0
- package/kit/studio/web/style.css +1453 -0
- package/package.json +46 -8
- package/start.sh +748 -0
- package/bin/crewforth.js +0 -10
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Panel mode — adversarial expert panel
|
|
2
|
+
|
|
3
|
+
For a **consequential, hard-to-reverse** decision (an architecture choice, a public API contract, a security
|
|
4
|
+
boundary) a single-lens review under-covers. Run an **adversarial expert panel**: evaluate the change from
|
|
5
|
+
**several independent lenses in parallel**, each arguing on its own terms, then synthesize.
|
|
6
|
+
- **Distinct lenses, not repetition:** e.g. *correctness/edge cases · security & privacy · maintainability &
|
|
7
|
+
altitude (YAGNI) · operational cost/perf*. Give each lens a real advocate whose job is to find where the
|
|
8
|
+
change fails on *that* axis — diversity catches failure modes redundancy can't.
|
|
9
|
+
- **Adversarial by default:** each lens tries to refute "this is the right change", not to bless it. A concern
|
|
10
|
+
raised by one lens isn't overruled by the others' approval — it's recorded and weighed.
|
|
11
|
+
- **Synthesize, don't average:** collect every lens's findings, keep the sharpest objection from each, and
|
|
12
|
+
reach one decision (proceed / proceed-with-changes / reject) with the reasoning. This is the distilled
|
|
13
|
+
judge-panel pattern — reserve it for high stakes; routine diffs get the single-lens review above (don't
|
|
14
|
+
burn a panel on a one-liner).
|
|
15
|
+
|
|
16
|
+
## The lenses (named, first-class)
|
|
17
|
+
|
|
18
|
+
Pick the lenses that fit the change — not all six every time. Each is a distinct advocate; assign one concern per
|
|
19
|
+
lens so they don't collapse into the same review twice.
|
|
20
|
+
|
|
21
|
+
| Lens | Asks | Fails the change when |
|
|
22
|
+
|---|---|---|
|
|
23
|
+
| **Correctness** | Does it do the right thing on every path? | An edge case, race, off-by-one, or error path is unhandled |
|
|
24
|
+
| **Security & privacy** | Can it be abused; does data leak? | Injection, missing authz, secret exposure, PII beyond purpose (→ `security-scan`, `privacy-compliance`) |
|
|
25
|
+
| **Simplicity & altitude** | Is it more than the problem needs? | Over-engineering, speculative generality, YAGNI, wrong abstraction level |
|
|
26
|
+
| **Contract & compatibility** | What breaks downstream? | A public API / schema / event shape changes without a migration or version (→ `api-design`) |
|
|
27
|
+
| **Operability** | What happens at 3am in prod? | No logs/metrics on the new path, silent failure, no rollback (→ `observability`, `incident-runbook`) |
|
|
28
|
+
| **Verifier integrity** | Is the *check* still honest? | A test/assertion/threshold was weakened to pass, instead of the behavior being fixed |
|
|
29
|
+
|
|
30
|
+
**Adversarial pairing:** the strongest panel pits lenses that pull against each other — Simplicity vs. Contract
|
|
31
|
+
(don't over-build, but don't break callers), Correctness vs. Operability (handle every case, but stay debuggable).
|
|
32
|
+
When two lenses conflict, that tension IS the decision to surface — resolve it explicitly, don't let one silently win.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Receiving a review — an inbound comment is a candidate, not an instruction
|
|
2
|
+
|
|
3
|
+
Read this on the skill's other mode: the review is someone else's and the code is yours — a teammate's comments, a
|
|
4
|
+
quality gate's report, a bot's PR review.
|
|
5
|
+
|
|
6
|
+
**Read every item before changing any line.** Comments are written one per symptom, and two of them
|
|
7
|
+
often share one cause; applying them in arrival order yields a patch per symptom instead of one fix at the cause.
|
|
8
|
+
Group by cause, then decide.
|
|
9
|
+
|
|
10
|
+
Each item then earns the same disprove pass as a finding of your own. Any "no" below is a reason to answer in the
|
|
11
|
+
thread, not to edit:
|
|
12
|
+
1. **Defect or preference?** Give each comment a severity and a category from SKILL.md — inbound prose arrives
|
|
13
|
+
unranked, you rank it, and only a `critical` or `high` blocks.
|
|
14
|
+
2. **Does it hold where the reviewer did not look?** Check the call sites and callers the comment never opened.
|
|
15
|
+
3. **Does it contradict a decision already recorded?** An `adr` or a documented constraint outranks the comment —
|
|
16
|
+
reopen the decision, do not quietly edit around it.
|
|
17
|
+
4. **Does the real check still pass with it applied?** Run it, don't re-read it. A suggestion that turns a check
|
|
18
|
+
red is reported back, and never satisfied by weakening the check (Verifier integrity, in SKILL.md).
|
|
19
|
+
5. **Is it against the current revision?** A comment on an older one may already be answered by a later commit.
|
|
20
|
+
|
|
21
|
+
Every inbound item leaves with a disposition from SKILL.md's triage table; none is left merely read. **A reasoned
|
|
22
|
+
refusal is an answer** — say why in the thread and let the reviewer press it or drop it. Not doing it quietly is not
|
|
23
|
+
an answer: it reads as agreement, and the same comment returns on the next review.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: crew-doctor
|
|
3
|
+
description: Health-check the install — hooks executable, core.hooksPath set, gates wired, discipline loaded.
|
|
4
|
+
metadata:
|
|
5
|
+
kind: command
|
|
6
|
+
---
|
|
7
|
+
# /crew-doctor
|
|
8
|
+
Verify Crewforth is actually *active* in this project (not just present on disk):
|
|
9
|
+
1. Run `bash .claude/eval/doctor.sh`.
|
|
10
|
+
2. Read its report. It checks: VERSION present · every hook executable · the required git hooks (pre-commit,
|
|
11
|
+
commit-msg) present · **guard-bash actually blocks a force-push** (catches a hook that is present but neutered) ·
|
|
12
|
+
`core.hooksPath` points at `.claude/hooks` (else the §4.1/§4.2 commit trace + secret/bloat scan never runs) ·
|
|
13
|
+
`settings.json` valid and wiring the PreToolUse / UserPromptSubmit / Stop gates to **non-empty** hook arrays
|
|
14
|
+
(an empty `[]` wires nothing); SessionStart (rehydration) is reported as a warning if absent · **`./CLAUDE.md`
|
|
15
|
+
actually imports `.claude/DISCIPLINE.md`** — without that line the discipline sits on disk and never loads, which
|
|
16
|
+
every other check is blind to.
|
|
17
|
+
3. For each ❌, apply the printed fix. Anything that changes git config or file permissions needs approval first —
|
|
18
|
+
show the exact command and wait.
|
|
19
|
+
4. Read the **Readiness** block too. It is advisory (never changes the verdict) and asks a different question — is
|
|
20
|
+
this *project* set up to be worked on by agents: CLAUDE.md project section filled in · a project-specific skill
|
|
21
|
+
alongside Crewforth's generic ones · a devcontainer to sandbox agent commands · an MCP server · CLAUDE.md not
|
|
22
|
+
drifted behind the code. Report the gaps as suggestions, not as failures, and never "fix" them unasked — adding
|
|
23
|
+
a devcontainer or an MCP server is the user's call.
|
|
24
|
+
5. Summarise: **healthy**, or the precise fixes applied/needed, plus the readiness score. If it's not a git repo,
|
|
25
|
+
note that the commit-time gates need `git init` + `git config core.hooksPath .claude/hooks`.
|
|
26
|
+
If the output contains a line starting with ⭐, pass it to the user verbatim as the LAST line of your summary —
|
|
27
|
+
it prints once per Crewforth version, and it is meant for the user, not for you.
|
|
28
|
+
|
|
29
|
+
If `.claude/eval/doctor.sh` doesn't exist, this is not a full (start.sh / adopt.sh) install — Crewforth is likely
|
|
30
|
+
running as a **plugin**, whose hooks are managed by Claude Code itself; there's nothing for the doctor to check.
|
|
31
|
+
|
|
32
|
+
**The eval scripts are installer-only, by decision.** `eval/` — `doctor.sh`, `smoke-test.sh`, `routing-eval.sh`,
|
|
33
|
+
`scan-skill.sh`, `utilization.sh` — ships with `start.sh` and `adopt.sh` and NOT with the plugin edition. The eval
|
|
34
|
+
scripts are developer instruments: they inspect an installation from outside it, and the plugin edition has no
|
|
35
|
+
installation to inspect. Say this plainly when someone asks why `/crew-doctor` reports nothing on a plugin install,
|
|
36
|
+
rather than treating it as a defect. The Studio panel ships in both editions (`/crew-studio`).
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: crew-gates
|
|
3
|
+
description: Gate report — what the tool-level gates actually did, and which rules nothing has tripped.
|
|
4
|
+
argument-hint: "[--log <path>]"
|
|
5
|
+
disable-model-invocation: true
|
|
6
|
+
metadata:
|
|
7
|
+
kind: command
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
Run the report and read it back to the user:
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
bash .claude/eval/gate-report.sh $ARGUMENTS
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Then interpret it in two sentences, in the user's language:
|
|
17
|
+
|
|
18
|
+
- **Exit 3 (no log).** Say plainly that gate activity is *not measured* — not that the gates never fired. Offer
|
|
19
|
+
the one-line opt-in the report prints. Do not present the rule count as if it were evidence of anything.
|
|
20
|
+
- **Exit 0.** Lead with the verdict split (how often the gates asked vs blocked). Then the notable rules: a rule
|
|
21
|
+
firing repeatedly is worth a conversation ("something keeps reaching for this"), and the not-observed list is
|
|
22
|
+
a prompt to check whether a rule *can* still match, not a delete list. `smoke-test` is what proves a rule can
|
|
23
|
+
fire; this only shows what tripped it.
|
|
24
|
+
|
|
25
|
+
Never infer that a gate works because it appears in the report, or that it is broken because it does not.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: crew-handoff
|
|
3
|
+
description: Session handover — SESSION_STATE.md + /clear suggestion.
|
|
4
|
+
metadata:
|
|
5
|
+
kind: command
|
|
6
|
+
---
|
|
7
|
+
# /crew-handoff
|
|
8
|
+
applies the `handoff` skill:
|
|
9
|
+
1. Read the measured fill: the `🔋 Session` line, or `bash .claude/hooks/context-usage.sh --verbose`.
|
|
10
|
+
2. Write an actionable handover to `docs/SESSION_STATE.md`: Done · In progress (exactly where) · Next step · Open decisions · File pointers · Blockers.
|
|
11
|
+
3. Preserve decision rationale; the next session should not start from scratch.
|
|
12
|
+
4. **Cold-reader pass** (`handoff/references/cold-reader.md`): the questions are written from the work BEFORE the
|
|
13
|
+
file, then answered from the file alone. Anything unanswerable goes back into the handover and is re-checked.
|
|
14
|
+
5. Once written — and only once every question is answerable — suggest `/clear`.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: crew-plan
|
|
3
|
+
description: Spec-first planning — break down ambiguously scoped work with crew-planner.
|
|
4
|
+
argument-hint: "[task/feature description]"
|
|
5
|
+
metadata:
|
|
6
|
+
kind: command
|
|
7
|
+
---
|
|
8
|
+
# /crew-plan
|
|
9
|
+
Argument: $ARGUMENTS
|
|
10
|
+
|
|
11
|
+
Delegate to the @agent-crew-planner agent (spec-planning skill). For ambiguously scoped work:
|
|
12
|
+
1. Clarify the goal + what's out of scope.
|
|
13
|
+
2. Split into vertical slices; give each task a measurable acceptance criterion.
|
|
14
|
+
3. Order by dependency + put the riskiest first.
|
|
15
|
+
4. Ask about ambiguities with **explicit options**; write down the assumptions.
|
|
16
|
+
|
|
17
|
+
Write the output to `docs/PLAN.md`, return a summary + pointer to the main thread (token-budget).
|
|
18
|
+
Do NOT write code — this is a planning step.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: crew-review
|
|
3
|
+
description: Review pass — review + security + quality gates.
|
|
4
|
+
metadata:
|
|
5
|
+
kind: command
|
|
6
|
+
---
|
|
7
|
+
# /crew-review
|
|
8
|
+
Run the change set through the review trio (read-only). **The audits go out in parallel; the reviewer closes.**
|
|
9
|
+
1. **At once, in ONE message** — several `Agent` calls, because none of these writes code and so there is
|
|
10
|
+
nothing to serialise:
|
|
11
|
+
- @agent-crew-security-expert (security-scan) — auth/IDOR/injection/secret; findings with severity.
|
|
12
|
+
- @agent-crew-performance-expert (`performance`) — hot path, query/loop, render, payload. Reports
|
|
13
|
+
**candidates** (reasoned) and **findings** (measured) separately; an unmeasured claim is never a verdict.
|
|
14
|
+
- @agent-crew-privacy-agent (`privacy-compliance`) — **when the diff touches personal data**: legal basis,
|
|
15
|
+
minimisation, retention, transfer.
|
|
16
|
+
2. (if SonarQube is in use) **sonarqube-check** — 0/0/0/0 gate (language-agnostic).
|
|
17
|
+
3. **Last, and only once 1-2 are clean:** @agent-crew-review-agent (code-review) — "does it improve overall code
|
|
18
|
+
health"; severity-ranked comments. It is the closing reviewer in every writing agent's Coordination ("at
|
|
19
|
+
closure, report findings to crew-review-agent"), so it reads a diff the audits have already cleared — not the
|
|
20
|
+
other way round.
|
|
21
|
+
|
|
22
|
+
Each agent returns a **short summary** to the main thread; raw output goes to `docs/` if needed. Do NOT modify code;
|
|
23
|
+
collect findings in severity order, and leave the fix to the relevant expert.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: crew-ship
|
|
3
|
+
description: DoD gate + commit proposal (waits for approval).
|
|
4
|
+
metadata:
|
|
5
|
+
kind: command
|
|
6
|
+
---
|
|
7
|
+
# /crew-ship
|
|
8
|
+
Closure flow — in order:
|
|
9
|
+
1. **DoD gate:** was `/simplify` applied · are tests green (@agent-crew-test-expert) · (if SonarQube is used) `sonarqube-check` 0/0/0/0.
|
|
10
|
+
If any one is red, **STOP**, report what is missing; no deferral.
|
|
11
|
+
2. If clean, @agent-crew-commit-agent (commit-message) **proposes** an atomic Conventional Commit from the staged diff.
|
|
12
|
+
3. Commit runs ONLY if the user says "commit" (§4.4). "Done" is not approval.
|
|
13
|
+
4. **Close the board item too** (`teamboard`), when one is held. Closing work is one movement: ask what shipped,
|
|
14
|
+
run `board.sh done <id> "<note>"`, name the items it unblocked, and offer the next one as options. Do not
|
|
15
|
+
leave this to the user to remember — a claim nobody closes reads to the whole team as still in progress, and
|
|
16
|
+
the items behind it stay unclaimable. If a decision came out of this work that changes how other items must
|
|
17
|
+
be done, record it with `board.sh decide` in the same breath; it is worthless in a session nobody else reads.
|
|
18
|
+
|
|
19
|
+
No destructive operations (§4.5). No AI trace / vendor name in the message (§4.1/§4.2 — the hook already scans).
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: crew-skill
|
|
3
|
+
description: Author or change a Crewforth component (skill / agent / command) against the template and its gates.
|
|
4
|
+
disable-model-invocation: true
|
|
5
|
+
metadata:
|
|
6
|
+
kind: command
|
|
7
|
+
---
|
|
8
|
+
# /crew-skill
|
|
9
|
+
|
|
10
|
+
`AGENT_TEMPLATE.md` states the contract for a component. Full installs carry it (refreshed on `update`); the
|
|
11
|
+
plugin edition does not. No gate routes to it, so this command is the route, and it ends in the gates.
|
|
12
|
+
|
|
13
|
+
**A component is not finished when it is written. It is finished when the suite says so.**
|
|
14
|
+
|
|
15
|
+
## 1. Decide the shape before writing anything
|
|
16
|
+
Read `.claude/AGENT_TEMPLATE.md`. Then answer, in one line each:
|
|
17
|
+
|
|
18
|
+
- **What is the smallest form that works?** A rule in an existing skill's body beats a new skill; a new skill beats
|
|
19
|
+
a new agent. Every new skill costs its NAME in every session, forever, for every user — and its description too,
|
|
20
|
+
until the listing overflows its budget, at which point descriptions start being dropped from the skills you
|
|
21
|
+
invoke least. Say what that buys.
|
|
22
|
+
- **Who reaches it?** An agent, a command, or the discipline's trigger map. If the answer is "the model will notice
|
|
23
|
+
the description", stop — that is the dark component §3b exists to catch.
|
|
24
|
+
- **Read or write?** A component that reports and a component that changes files do not belong together: different
|
|
25
|
+
risk, different done-criterion. Split them.
|
|
26
|
+
- **Is it stack-neutral?** Anything shipped to every profile names no language, framework or vendor as *the* case.
|
|
27
|
+
The example you have in mind is not the scope.
|
|
28
|
+
|
|
29
|
+
## 2. Write it
|
|
30
|
+
- Skill: `.claude/skills/<name>/SKILL.md` — the directory name and the `name:` field must match. Keep the body
|
|
31
|
+
lean; depth goes to `references/*.md` and is loaded on demand.
|
|
32
|
+
- Agent: a thin trigger — *who and when*. The *how* lives in the skill it applies; do not copy the method in.
|
|
33
|
+
- The `description` says **when to reach for this**, not what its author knows.
|
|
34
|
+
|
|
35
|
+
## 3. Register it — the cascade, in this order
|
|
36
|
+
Skipping one of these is how a component ships half-installed:
|
|
37
|
+
1. **Route it.** Name it in an agent body, a command, or the trigger map. §3b checks exactly this.
|
|
38
|
+
2. **Golden case.** Add a positive line to `.claude/eval/golden-routing.txt` — and a **negative** one
|
|
39
|
+
(`prompt|!target`) for a neighbour it must NOT steal.
|
|
40
|
+
3. **Catalog + counts** *(Crewforth repository only — `packaging/` is not installed anywhere)*.
|
|
41
|
+
Add the Turkish summary line (`packaging/skill-summaries.tr.tsv`; agents and commands have their own `.tr.tsv`),
|
|
42
|
+
which the site build requires (`cd site && npm ci && npm run build`), and the diagrams if the component set changed:
|
|
43
|
+
`node packaging/gen-diagrams.mjs` writes `assets/`, and smoke fails while any of them is stale.
|
|
44
|
+
4. **Plugin edition** *(Crewforth repository only)*. `bash packaging/build-plugin.sh` — in the same commit, or the
|
|
45
|
+
release stops at the sync gate.
|
|
46
|
+
5. **Budget.** A new skill moves `BUDGET_SKILLS`; raise it in the same commit with the justification comment the
|
|
47
|
+
file's convention requires. Never raise it to make a red gate green without saying why.
|
|
48
|
+
|
|
49
|
+
## 4. Prove it — run all four, in this order
|
|
50
|
+
```
|
|
51
|
+
bash .claude/eval/scan-skill.sh .claude/skills/<name> # supply-chain: SAFE, and rc=3 means NOT scanned
|
|
52
|
+
bash .claude/eval/routing-eval.sh # the golden case, positive and negative
|
|
53
|
+
bash .claude/eval/smoke-test.sh # structure, budget, §3b routed, cross-links
|
|
54
|
+
CREW_NO_STAR=1 bash .claude/eval/doctor.sh # the live install still healthy (star line off here)
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
In the plugin edition none of the four commands above exist — it ships no `eval/` at all — so there the proof is
|
|
58
|
+
the Crewforth repository's own suite, not a local run.
|
|
59
|
+
|
|
60
|
+
**Do not finish while §3b is red.** "It works when I invoke it by name" is not the claim being tested — the claim
|
|
61
|
+
is that something reaches it without being told to. If the suite skips a case, that is not a pass: chase why.
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: crew-studio
|
|
3
|
+
description: Open Crewforth Studio — the visual panel for what agents are doing, what they spent, and which gates fired.
|
|
4
|
+
argument-hint: "[--port <n>]"
|
|
5
|
+
disable-model-invocation: true
|
|
6
|
+
metadata:
|
|
7
|
+
kind: command
|
|
8
|
+
---
|
|
9
|
+
# /crew-studio
|
|
10
|
+
|
|
11
|
+
Start the panel and hand the user its URL. Never leave a half-started server behind: if any step below
|
|
12
|
+
fails, say which one and stop — do not improvise a different launch.
|
|
13
|
+
|
|
14
|
+
1. **Resolve the panel.** Both editions carry it, in different places, and this one file serves both.
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
PLUGIN_PANEL=${CLAUDE_PLUGIN_ROOT}/studio/server/index.js
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Claude Code replaces `${CLAUDE_PLUGIN_ROOT}` in this text **before you read it**, and only when this
|
|
21
|
+
command came from the plugin. So read the line above literally:
|
|
22
|
+
|
|
23
|
+
- It names a real absolute path → **plugin edition**. That is the panel. Use it.
|
|
24
|
+
- It still contains the characters `${CLAUDE_PLUGIN_ROOT}` → this is a **full install**. The panel is
|
|
25
|
+
`.claude/studio/server/index.js`.
|
|
26
|
+
|
|
27
|
+
The variable is not in the shell's environment — it is text substituted into this file — so never try
|
|
28
|
+
to read it with `printenv` or let a shell expand it. Never write the unbraced `$CLAUDE_PLUGIN_ROOT`
|
|
29
|
+
either; only the braced form is substituted, and the unbraced one reaches bash unset and collapses the
|
|
30
|
+
path to `/studio/server/index.js`.
|
|
31
|
+
|
|
32
|
+
Neither path is there? Then this is an install older than the release that added the panel:
|
|
33
|
+
`npx crewforth@latest update --here --yes` at the project root, or `/crew-update`.
|
|
34
|
+
Then stop. Do not go hunting for the panel anywhere else on disk.
|
|
35
|
+
|
|
36
|
+
**What the plugin edition cannot show.** A plugin install puts no `.claude/VERSION`, `kit.conf` or Crewforth
|
|
37
|
+
scripts into a project. So that project's row in the list has no version badge (each row reads its own
|
|
38
|
+
project), and for the project you opened the panel from, the inspector's gates, stats and board tabs
|
|
39
|
+
say "Not measured" with the reason, rather than zero. The gates tab can still list observed entries
|
|
40
|
+
below that. The plugin's Bash guard logs its blocks, approval prompts and `CLAUDE_GIT_OK` pre-authorised
|
|
41
|
+
git actions, and its gate-file write guard logs its blocks, to `.claude/gate-log.tsv` when the project
|
|
42
|
+
has a `.claude/` directory and the file is git-ignored or the project is not a repo. With `CREW_GATE_LOG`
|
|
43
|
+
set they write wherever it points instead, and the panel reads only the project's own
|
|
44
|
+
`.claude/gate-log.tsv`, so a log sent anywhere else does not show. The commit scan and the board gate
|
|
45
|
+
refuse without writing a line. Say this once when you hand over the URL, so an honest blank is not
|
|
46
|
+
read as a broken panel. Everything else — the live agent graph, owned sessions, the permission bridge —
|
|
47
|
+
works the same in both editions.
|
|
48
|
+
|
|
49
|
+
2. **Resolve a runtime — do not ask whether a name resolves.** `ensure-node.sh` sits one level ABOVE the panel
|
|
50
|
+
— beside the `server/` directory, not inside it. Both spellings, in full, so there is nothing to guess:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
bash .claude/studio/ensure-node.sh --explain # full install
|
|
54
|
+
bash ${CLAUDE_PLUGIN_ROOT}/studio/ensure-node.sh --explain # plugin edition (step 1 decided which)
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
It prints the absolute path of a Node 18+ that actually runs, and exits 1 when there is none. Use that path;
|
|
58
|
+
do not assume it is `node`. It looks in places PATH does not reach — a version manager puts node on
|
|
59
|
+
PATH from a login shell only, so "nvm is installed" and "this shell can see node" are different
|
|
60
|
+
facts. And it runs what it finds rather than trusting the name: the Windows Store ships a stub that
|
|
61
|
+
satisfies `command -v`, prints nothing and exits 49.
|
|
62
|
+
|
|
63
|
+
**No `ensure-node.sh` beside the panel?** Then the panel predates the fetcher. Fall back to running
|
|
64
|
+
`node --version` and reading the output — 18+ required — and tell the user `/crew-update` brings the
|
|
65
|
+
fetcher along with everything else.
|
|
66
|
+
|
|
67
|
+
3. **No runtime? Crewforth gets one — after the user says so.** Show them what it would do, then ask:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
bash <the same path as step 2> --plan # url, size, checksum source, target directory
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
It fetches the current Node LTS from nodejs.org into `~/.claude/studio-runtime`, verifies it against
|
|
74
|
+
the published SHA-256 and refuses to install on a mismatch. Nothing else on the machine is touched:
|
|
75
|
+
no admin rights, no package manager, no PATH or profile edit. Deleting that one directory undoes it.
|
|
76
|
+
|
|
77
|
+
Ask with `AskUserQuestion`, and offer the alternative honestly — some people would rather their own
|
|
78
|
+
package manager owned it (`winget install OpenJS.NodeJS.LTS`, `brew install node`, or their distro's).
|
|
79
|
+
On yes:
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
bash <the same path as step 2> --install # prints the node path on success
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Never run `--install --yes` on the user's behalf without that answer, and never install anything
|
|
86
|
+
system-wide.
|
|
87
|
+
|
|
88
|
+
4. **Start it in the background**, from the project root, with the node from step 2 or 3:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
"$NODE" <panel> --open
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
It prints a tokenised URL (`http://127.0.0.1:7777/?token=…`) and keeps running. **Report that URL**
|
|
95
|
+
whether or not a browser opened — over SSH or headless nothing can open, and a running server with no
|
|
96
|
+
way in is the worst outcome here. Tell the user it runs until they stop it, and how (Ctrl-C in that
|
|
97
|
+
shell, or kill the process). Do not hold it in a foreground tool call.
|
|
98
|
+
|
|
99
|
+
5. **Port already in use.** Start it anyway and read what it says — the panel checks whether the holder is
|
|
100
|
+
another crewforth-studio first, and there is nothing for you to decide before it does. Two answers:
|
|
101
|
+
|
|
102
|
+
- `already running on port <n> (pid …) — reusing it`, followed by a tokenised URL and exit 0. That is a
|
|
103
|
+
panel someone else started, usually another session in this project. **Report that URL**; it is the same
|
|
104
|
+
panel, and the token in it is the running instance's own. Tell the user it belongs to whoever started it,
|
|
105
|
+
so closing this shell does not stop it.
|
|
106
|
+
- `held by something that is not a crewforth-studio panel` and exit 1. Then retry once with `--port <n+1>` and
|
|
107
|
+
report the new URL. If that port is taken too, stop and say both are taken rather than walking up the
|
|
108
|
+
range — something is listening that the user should look at.
|
|
109
|
+
|
|
110
|
+
The record that makes the first answer possible lives in `~/.claude/studio-runtime/instance-<port>.json`,
|
|
111
|
+
0600, and holds the token. A panel that was killed leaves one behind; the next start probes it, gets no
|
|
112
|
+
answer, and deletes it — so a stale file reports as the second answer, never as a URL that does not open.
|
|
113
|
+
|
|
114
|
+
**Quoting the panel's output.** It prints two things that belong to this machine and nowhere else: the machine
|
|
115
|
+
NAME, and a URL carrying a freshly generated token. Handing both to the user is the whole point — they are
|
|
116
|
+
sitting at that machine. Putting either into anything that leaves it is not: a commit message, a PR, a
|
|
117
|
+
CHANGELOG, an issue, a report to another session. The name is a §4.3 private term, and the token is a
|
|
118
|
+
credential, loopback-scoped but still live for as long as that panel runs. So when you quote panel output
|
|
119
|
+
anywhere but to the user, drop the machine line and replace the token with `…`. `.private-terms.txt` catches
|
|
120
|
+
the name only if someone thought to add it; nothing catches the token.
|
|
121
|
+
|
|
122
|
+
**What the panel's scope actually is.** It reads `~/.claude/projects` — every Claude Code session on this
|
|
123
|
+
machine, not this project's. Starting it from a project root only decides which project it opens on. Say
|
|
124
|
+
that when you hand over the URL, so nobody reports "it shows other projects" as a bug.
|
|
125
|
+
|
|
126
|
+
Offline diagnostic, no browser and no tokens: `"$NODE" <panel> --selftest`.
|
|
127
|
+
|
|
128
|
+
**In the plugin edition this command is namespaced** — `/crewforth:crew-studio`, not
|
|
129
|
+
`/crew-studio`. Measured: the bare name does not resolve for a plugin command.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: crew-update
|
|
3
|
+
description: Check for a newer version, update, report what changed, then prompt /clear to reload.
|
|
4
|
+
metadata:
|
|
5
|
+
kind: command
|
|
6
|
+
---
|
|
7
|
+
# /crew-update
|
|
8
|
+
Bring the Crewforth install up to the latest published version:
|
|
9
|
+
1. **Detect install type.** If `.claude/VERSION` exists → a full install (steps below). If Crewforth runs as a
|
|
10
|
+
**plugin** (no `.claude/VERSION`), it updates through the plugin system: run
|
|
11
|
+
`claude plugin update crewforth@crewforth`, tell the user it applies when they restart Claude Code, and stop here.
|
|
12
|
+
2. **Current version:** read `.claude/VERSION`.
|
|
13
|
+
3. **Latest version:** `npm view crewforth version` (needs network). If it can't be reached,
|
|
14
|
+
say so and stop — don't guess.
|
|
15
|
+
4. **Compare.** Already on the latest → report "up to date (vX)" and stop. Otherwise show **old → new**.
|
|
16
|
+
5. **Before:** run `bash .claude/eval/update-guard.sh pre`. It records what is on disk (in `.claude/.state/`, nothing
|
|
17
|
+
else) and prints one of three verdicts:
|
|
18
|
+
- `clean` → nothing to report, go on.
|
|
19
|
+
- `UNCOMMITTED:` with the changed paths in `.claude/` and `CLAUDE.md` → show the user that list and **ask** —
|
|
20
|
+
with your question tool — whether to go ahead (the update rewrites Crewforth-owned files under `.claude/`), commit
|
|
21
|
+
or stash first, or stop. Continue only on their yes.
|
|
22
|
+
- `NOT IN GIT:` (a private install gitignores `.claude/` and `CLAUDE.md`, so edits there cannot be detected) →
|
|
23
|
+
pass its two lines to the user and go on; there is nothing to commit.
|
|
24
|
+
6. **Update** — this rewrites Crewforth-owned files under `.claude/` (your `./CLAUDE.md` and project skills are
|
|
25
|
+
preserved). **Show this plan first, then run:** `npx --yes crewforth@latest update --here --yes`.
|
|
26
|
+
Two DIFFERENT `--yes` flags, both required for a non-interactive run: the one **before** the package name is
|
|
27
|
+
**npx's own** — it auto-confirms npx's `Ok to proceed?` install prompt, which reads the real TTY and IGNORES piped
|
|
28
|
+
input, so without it the command hangs before Crewforth even starts. The `--here --yes` **after** the package go to
|
|
29
|
+
the updater (`--here` = apply on the current branch, `--yes` = accept the smart defaults). Together they let it run
|
|
30
|
+
to completion instead of blocking on a prompt your shell can't answer.
|
|
31
|
+
If you'd rather review each handover decision yourself, tell the user to run `npx crewforth@latest update`
|
|
32
|
+
(no flags) in **their own terminal**, where both the npx and the interactive prompts work.
|
|
33
|
+
7. **After:** run `bash .claude/eval/update-guard.sh post` and show the user its lists — added, changed, moved,
|
|
34
|
+
removed.
|
|
35
|
+
8. **Verify:** run `/crew-doctor` (or `bash .claude/eval/doctor.sh`) so a bad/partial update surfaces immediately.
|
|
36
|
+
If the updater's or doctor's output contains a line starting with ⭐, pass it to the user verbatim as the LAST
|
|
37
|
+
line of your summary — it prints once per Crewforth version, and it is meant for the user, not for you.
|
|
38
|
+
9. **Report** old → new + the headline changes. Take them from `.claude/.state/whats-new.md` — the updater writes
|
|
39
|
+
there the installed package's own CHANGELOG sections between the old and the new version. Do not fetch release
|
|
40
|
+
notes from the network. No file → say no release notes were included.
|
|
41
|
+
10. **Reload (manual — a command can't do it itself):** the discipline in the running session is still the OLD one.
|
|
42
|
+
Tell the user to run **`/clear`** (or quit and relaunch Claude Code): a new session loads the updated
|
|
43
|
+
`.claude/DISCIPLINE.md`.
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: db-migration
|
|
3
|
+
description: |
|
|
4
|
+
Apply schema migrations safely: detect the tool, classify the change by risk, gate destructive ones behind
|
|
5
|
+
approval, back up in prod, preview-apply-verify, roll back on failure.
|
|
6
|
+
Use when a schema change is about to be applied to any environment.
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Database Migration
|
|
10
|
+
|
|
11
|
+
<!-- routing-eval reads the next line; why it sits in the body: AGENT_TEMPLATE.md -->
|
|
12
|
+
Trigger phrases: "migration", "schema change", "update database", "add column", "create table", "alter table", "add a column to", "adding a column to", "drop a column", "rename the table", "change the column type", "backfill"
|
|
13
|
+
|
|
14
|
+
A migration is very often a **one-way gate**: once applied, going back is expensive or impossible
|
|
15
|
+
unless it was planned for. That is why the heart of the flow is not running a command, but **classifying
|
|
16
|
+
the change by risk class before it passes through the gate** — let the safe one flow through, stop and
|
|
17
|
+
get approval for the destructive one, and keep a rollback path ready in every case. The skill works with
|
|
18
|
+
all common ORM/migration tools.
|
|
19
|
+
|
|
20
|
+
> **Crewforth adaptation (local, .claude/):** Engine and tool come from `CLAUDE.md ## Stack` or repo detection
|
|
21
|
+
> (`backend-architecture`). `crew-database-expert` applies it; **a destructive migration requires explicit approval (§4.5)**, commit/push with explicit approval (§4.4). Authorization/IDOR
|
|
22
|
+
> impact → **crew-security-expert**; personal-data retention → **crew-privacy-agent**. §4 Prohibitions apply.
|
|
23
|
+
|
|
24
|
+
## Checklist
|
|
25
|
+
- [ ] Tool detected, pending migrations listed
|
|
26
|
+
- [ ] Every change classified (additive / destructive / ambiguous)
|
|
27
|
+
- [ ] Destructive/ambiguous changes approved by the user
|
|
28
|
+
- [ ] Backup taken (mandatory in prod, verified)
|
|
29
|
+
- [ ] Preview (dry-run) shown and approved
|
|
30
|
+
- [ ] Applied, schema verified post-apply
|
|
31
|
+
- [ ] Rollback path (tool or backup) ready
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## 1. Detect the tool
|
|
36
|
+
|
|
37
|
+
Determine the tool from the file trace; if none is found, fall back to **raw SQL mode** (below); if several are found, ask the user.
|
|
38
|
+
|
|
39
|
+
| Trace | Tool |
|
|
40
|
+
|---|---|
|
|
41
|
+
| `prisma/schema.prisma` | Prisma |
|
|
42
|
+
| `knexfile.{js,ts}` | Knex |
|
|
43
|
+
| `.sequelizerc` / `config/config.json` + `models/` | Sequelize |
|
|
44
|
+
| `data-source.ts` (typeorm) / `ormconfig.ts` | TypeORM |
|
|
45
|
+
| `drizzle.config.ts` | Drizzle |
|
|
46
|
+
| `alembic.ini` / `alembic/` | Alembic |
|
|
47
|
+
| `manage.py` + `django` dependency | Django |
|
|
48
|
+
| `db/migrate/` + `rails` in Gemfile | Rails |
|
|
49
|
+
| `Microsoft.EntityFrameworkCore` in `*.csproj` + `Migrations/` | EF Core |
|
|
50
|
+
|
|
51
|
+
---
|
|
52
|
+
|
|
53
|
+
## 2. Classify the change — the heart of the flow
|
|
54
|
+
|
|
55
|
+
Extract the SQL to be applied (the "Preview" column in the matrix below) and place it into one of three classes:
|
|
56
|
+
|
|
57
|
+
| Class | Example operations | How it is handled |
|
|
58
|
+
|---|---|---|
|
|
59
|
+
| **Additive** (safe) | `CREATE TABLE`, nullable/defaulted `ADD COLUMN`, `CREATE INDEX`, non-destructive `ADD CONSTRAINT`, seed `INSERT` | Proceed in the normal flow |
|
|
60
|
+
| **Destructive** (dangerous) | `DROP TABLE/COLUMN/INDEX/CONSTRAINT`, `ALTER COLUMN … TYPE`, `TRUNCATE`, `DELETE` without WHERE, `RENAME` (breaks references) | **Always the approval gate** (below) |
|
|
61
|
+
| **Ambiguous** (human judgment) | `ALTER COLUMN`, `ADD COLUMN NOT NULL` without a default (blows up on a populated table), `UPDATE`, mixed migration | **Treat as destructive**, warn and ask |
|
|
62
|
+
|
|
63
|
+
**Approval gate (destructive/ambiguous):** list the operations one by one, show the environment and the target, wait for explicit approval. Even if "run" was said in the general flow, this gate requires separate approval.
|
|
64
|
+
```
|
|
65
|
+
WARNING — this migration contains a destructive operation:
|
|
66
|
+
· DROP COLUMN "legacy_email" (table: users)
|
|
67
|
+
· ALTER COLUMN "status" TYPE integer (table: orders)
|
|
68
|
+
CANNOT BE UNDONE without a backup. Target: production (myapp_db @ db.example.com)
|
|
69
|
+
Continue? (yes / no)
|
|
70
|
+
```
|
|
71
|
+
If rejected, stop immediately and propose a safer path (e.g. a new column + background copy instead of changing the type).
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## 3. Backup (mandatory in prod)
|
|
76
|
+
|
|
77
|
+
Back up before any migration; it cannot be skipped in prod, and can be skipped in dev with approval. Then verify
|
|
78
|
+
**the backup was created and is not empty** — otherwise abort:
|
|
79
|
+
```bash
|
|
80
|
+
[ -s "$BACKUP_FILE" ] || { echo "ERROR: Backup empty/not created — migration aborted."; exit 1; }
|
|
81
|
+
```
|
|
82
|
+
Backup + restore + post-apply verify commands **per engine** (PostgreSQL · MySQL · SQLite):
|
|
83
|
+
**`references/backup-restore.md`** — read the one for your database, not all three.
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## 4. Tool × life-cycle matrix
|
|
88
|
+
|
|
89
|
+
Once classification and backup are complete: **Preview → (approval) → Apply → Verify**.
|
|
90
|
+
|
|
91
|
+
Per-tool commands for those four steps and for rollback — Prisma, Knex, Sequelize, TypeORM, Drizzle, Alembic, Django, Rails, EF Core: **`references/tool-matrix.md`**. Look up the one the project uses.
|
|
92
|
+
|
|
93
|
+
**Rules:** **Always** show the preview before applying and get it approved (if the tool does not support a dry-run, treat the migration file itself as the preview). A destructive migration is not applied without passing the approval gate (§2). Show the full apply output; if there is an error, roll back.
|
|
94
|
+
|
|
95
|
+
**Additional post-apply verification** — compare against the expected schema using your engine's inspect command (`references/backup-restore.md`).
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## 5. Rollback
|
|
100
|
+
|
|
101
|
+
First the tool-specific rollback (last column of the matrix); if that fails, restore from the backup (per-engine
|
|
102
|
+
restore command in **`references/backup-restore.md`**); then re-verify. If neither works, warn the user with the full error detail.
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## No tool — raw SQL mode
|
|
107
|
+
|
|
108
|
+
If no tool is detected, manage numbered up/down files (every `up` has a `down`, each SQL inside `BEGIN`/`COMMIT`)
|
|
109
|
+
with a `_migrations` tracking table. Full pattern + example + the apply loop: **`references/raw-sql.md`**.
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## Invariant rules
|
|
114
|
+
1. **Classify first** — additive/destructive/ambiguous; treat the ambiguous as destructive.
|
|
115
|
+
2. **Destructive = human approval** — a separate gate even in an automated flow.
|
|
116
|
+
3. **Prod backup mandatory** — no apply without a verified backup.
|
|
117
|
+
4. **Preview on by default** — opting out requires an explicit request.
|
|
118
|
+
5. **Always verify after applying.**
|
|
119
|
+
6. **Rollback path always ready** — tool or backup.
|
|
120
|
+
7. **Show the target** — DB name/host/environment, before applying.
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Backup & restore — per engine
|
|
2
|
+
|
|
3
|
+
Take the backup **before** any migration (mandatory in prod; dev may skip with approval), then verify it is
|
|
4
|
+
non-empty or abort. Rollback order: the tool-specific rollback first (matrix, last column) → if it fails, restore
|
|
5
|
+
from this backup → re-verify. Read **only the section for your database**.
|
|
6
|
+
|
|
7
|
+
## PostgreSQL
|
|
8
|
+
```bash
|
|
9
|
+
# backup — compressed full dump
|
|
10
|
+
pg_dump -h $DB_HOST -U $DB_USER -d $DB_NAME -F c -f backup_$(date +%Y%m%d_%H%M%S).dump
|
|
11
|
+
# restore (rollback)
|
|
12
|
+
pg_restore -h $DB_HOST -U $DB_USER -d $DB_NAME --clean --if-exists $BACKUP_FILE
|
|
13
|
+
# post-apply verify
|
|
14
|
+
psql -h $DB_HOST -U $DB_USER -d $DB_NAME -c "\d $TABLE"
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## MySQL
|
|
18
|
+
```bash
|
|
19
|
+
# backup
|
|
20
|
+
mysqldump -h $DB_HOST -u $DB_USER -p$DB_PASS $DB_NAME > backup_$(date +%Y%m%d_%H%M%S).sql
|
|
21
|
+
# restore (rollback)
|
|
22
|
+
mysql -h $DB_HOST -u $DB_USER -p$DB_PASS $DB_NAME < $BACKUP_FILE
|
|
23
|
+
# post-apply verify
|
|
24
|
+
mysql -h $DB_HOST -u $DB_USER -p$DB_PASS $DB_NAME -e "DESCRIBE $TABLE;"
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## SQLite
|
|
28
|
+
```bash
|
|
29
|
+
# backup
|
|
30
|
+
sqlite3 $DB_PATH ".backup 'backup_$(date +%Y%m%d_%H%M%S).db'"
|
|
31
|
+
# restore (rollback)
|
|
32
|
+
cp $BACKUP_FILE $DB_PATH
|
|
33
|
+
```
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# No tool — raw SQL mode
|
|
2
|
+
|
|
3
|
+
If no migration tool is detected, manage numbered up/down files; every `up` has a `down`, and every SQL runs
|
|
4
|
+
inside `BEGIN`/`COMMIT`.
|
|
5
|
+
```
|
|
6
|
+
migrations/001_create_users.up.sql + 001_create_users.down.sql
|
|
7
|
+
```
|
|
8
|
+
```sql
|
|
9
|
+
-- 001_create_users.up.sql
|
|
10
|
+
BEGIN;
|
|
11
|
+
CREATE TABLE IF NOT EXISTS users (
|
|
12
|
+
id SERIAL PRIMARY KEY,
|
|
13
|
+
email VARCHAR(255) NOT NULL UNIQUE,
|
|
14
|
+
created_at TIMESTAMP NOT NULL DEFAULT NOW()
|
|
15
|
+
);
|
|
16
|
+
COMMIT;
|
|
17
|
+
-- 001_create_users.down.sql
|
|
18
|
+
BEGIN;
|
|
19
|
+
DROP TABLE IF EXISTS users;
|
|
20
|
+
COMMIT;
|
|
21
|
+
```
|
|
22
|
+
Keep the applied ones in a tracking table; run only those with no record:
|
|
23
|
+
```bash
|
|
24
|
+
psql … -c "CREATE TABLE IF NOT EXISTS _migrations(id SERIAL PRIMARY KEY, name TEXT UNIQUE, applied_at TIMESTAMP DEFAULT NOW())"
|
|
25
|
+
for f in migrations/*.up.sql; do
|
|
26
|
+
n=$(basename "$f" .up.sql)
|
|
27
|
+
[ "$(psql … -tAc "SELECT count(*) FROM _migrations WHERE name='$n'")" = 0 ] || continue
|
|
28
|
+
psql … -f "$f" && psql … -c "INSERT INTO _migrations(name) VALUES('$n')"
|
|
29
|
+
done
|
|
30
|
+
```
|