Validate, branch, commit, and create PR following Hephaestus conventions. Use when ready to ship changes, create a pull request, or push work.
Follow the writing standard for all prose.
git status --short
git diff --name-only HEAD
Nothing staged or modified means nothing to land.
detect-changes in .github/workflows/cicd.yml holds the path filters.
Read it instead of guessing.
Two path groups need attention:
docs/**, scripts/**, and the root lint, format, and tsconfig files select the Tooling and Docs leg.
They do not select the App Server leg.package.json or pnpm-lock.yaml select every source leg.vp run format
vp run check
check is the complete local quality gate: every gate in the quality group in vite.config.ts,
and every one also runs in CI. CI also runs service tests, builds, images,
security checks, and workflow-specific gates. Formatting must never be the reason a remote build
fails.
Generated artefacts are never hand-edited, and regeneration is destructive โ it empties the target directory first, so stash local edits.
vp run generate:api # controllers or DTOs changed: rewrites openapi.yaml AND webapp/src/api
vp run db:draft-changelog # entities changed (needs Docker); writes and wires the changelog, then prune it
vp run db:generate-erd-docs # after pruning a changelog
generate:api:specs packages the server and boots the executable JAR on ports
it allocates itself.
Thus, no ports need to be freed.
Root AGENTS.md ยง Command caveats covers the HEPHAESTUS_APPLICATION_JAR shortcut for a JAR you already built.
vp run test:webapp
vp run test:server:unit
Regeneration produces unformatted output. Run step 3 again. Both commands must pass on the final tree.
A PR touching server/, webapp/ or docker/ needs a .changeset/*.md or verify-changesets
fails it.
vp exec changeset # user-facing: pick the bump, write the summary in the operator's voice
vp exec changeset --empty # no user-facing effect; say why in the body
vp exec changeset is interactive.
With no TTY, hand-write .changeset/<slug>.md.
.changeset/README.md owns the rules:
minor with **Operators:** and a .migration/<slug>.md fragment.MIGRATION.md.Changing db/changelog/ without changing .changeset/ is always wrong.
git branch --show-current # if main, branch first
git checkout -b <type>/<description>
git add -A
git commit -m "<type>(<scope>): <description>"
git push -u origin HEAD
Types and scopes are enumerated in commitlint.config.ts, which is what validates the PR title โ
read it there instead of in a copy.
Do not put ! in the title.
The changeset, not the header, carries pre-1.0 breaking changes.
PAGER=cat gh pr view --json number,url
If that reports that the current branch has no pull request, create it:
PAGER=cat gh pr create --base main --title "<type>(<scope>): <description>" --body "$(cat <<'BODY'
## What changed and why
<1-2 sentences: what and why>
## How to test
<manual steps, or "CI covers this">
## Release impact
<link the changeset and state operator action, or explain why neither applies>
## Notes for reviewers
<risks, tradeoffs, follow-up work, or delete this section>
## Visual evidence
<UI: before and after. Motion or timing: a short video. Otherwise delete this section.>
BODY
)"
For a UI change, save PR-only evidence under the ignored tmp/ directory and inspect it for
secrets, personal data, and unrelated content. Give each image alt text that describes the visible
state. For a video, describe the behavior that the video shows in the PR body.
mkdir -p tmp
gh pr edit --attach './tmp/before.png#Settings before the change' --attach './tmp/after.png#Settings after the change'
An upload can add earlier files before a later file fails. Inspect the PR before retrying, then attach only the missing files.
PAGER=cat gh pr view --json url,title -q '"PR: \(.title)\nURL: \(.url)"'
Open the URL and check that every attachment renders, describes the intended state, and contains no sensitive or unrelated content.