Skip to content
DezfilDocsv0.1.0

How this is built

Take a change from an idea to main: describe the behavior, build it on a branch with its tests, pass the checks and get it reviewed.

Every change to Dezfil takes the same steps, whether a person or an AI coding agent writes it:

StepWhat you doWhat holds it
1. DescribeSay what a user will notice, in an issueThe issue forms
2. BuildCommit on a branch, with testsConventional Commits and a sign-off
3. CheckRun the checks before you pushThe pipeline, on every pull request
4. Open a pull requestSay what changed and how you checked itThe pull request template
5. ReviewA second reader reads the diffThe reviewer, then a maintainer’s merge

For anything larger than a typo, open an issue first, at https://github.com/Dezfil/Dezfil/issues/new/choose. Pick the form that fits:

FormWhat it asks for
Feature requestThe problem, the behavior you would like from a user’s point of view, and what you do today instead
Bug reportWhat happened, the steps to reproduce it, the version, how you run Dezfil, and any logs

You should see your issue open with the label its form sets: enhancement or bug.

Describe behavior, not code: what a user will see or be able to do, how you will know it works, and what the change leaves out.

The costlier a mistake would be, the more you describe first. If the change breaks the API, as Architecture defines a breaking change, say so in the issue.

Report a security problem privately, as SECURITY.md says, never in an issue. Ask questions in Discussions.

Terminal
git switch -c fix/legend-range main
git add <CHANGED_FILES>
git commit -s -m "fix(legend): show the new range after a colormap change"
git log -1 --format=%B
Output
fix(legend): show the new range after a colormap change
Signed-off-by: <YOUR_NAME> <<YOUR_EMAIL>>
  • fix/legend-range names the branch by its kind and its subject. Cut it from main and keep it to one subject: a defect you find on the way past gets its own issue.
  • git add <CHANGED_FILES> stages the files you edited, so the commit takes them.
  • fix(legend): ... is a Conventional Commits message: a type, an optional scope, then what the change does.
  • -s adds the Signed-off-by line from your user.name and user.email. With it you certify the Developer Certificate of Origin, under your real name.

Write a body for anything substantial: why, the behavior that results, how you checked it and what that did not cover. Contributing lists the commit types and holds the certificate.

A change ships with its tests. Prefer a test that fails before the change and passes after it: a test that cannot fail only turns an assumption into a green tick.

Keep to these while you build:

  • API first: new behavior starts as a documented API operation, which the UI calls like any other client. What a person can do in the app, an agent can do too.
  • Docs in the same change: if a page under docs/ describes what you changed, fix the page too. Write a docs page holds the rules.
  • Large modules shrink: the oversized modules listed in scripts/check-monster-files.mjs must not grow. Extract the piece you touch, and start new logic in a new module.
  • Borrowed code keeps its header: code from a permissively licensed project keeps its licence header and gets a line in NOTICE. Copyleft code is reference only.

If an AI coding agent writes the change, start it on AGENTS.md. It holds the constraints every change keeps, and points the agent at the documentation index.

Terminal
npm run lint
NODE_OPTIONS=--max-old-space-size=4096 npm run typecheck
DEZFIL_DATA_DIR="$(mktemp -d)" npm test
  • npm run lint runs ESLint over the repository.
  • npm run typecheck checks the types with the TypeScript compiler and emits no JavaScript. NODE_OPTIONS gives it 4 GB of heap, as the pipeline does.
  • npm test runs the unit and integration suite. DEZFIL_DATA_DIR gives it an empty scratch folder, so the suite never touches your real data. Its tile tests need tippecanoe on your PATH: Development setup says how to install it.

You should see each command finish without an error.

Each narrower check, such as npm run lint:docs, holds one property of the repository. Run the ones your change could break. Development setup lists them all.

The pipeline runs the checks again on every pull request and every push to main, and a new push to a pull request cancels the run still going:

JobWhen it runsWhat it does
checksEvery pull request and every push to mainLint, types, every narrower check, the unit suite, and the two checks of the ingress preload
secretsEvery pull request and every push to mainScans the working tree for secrets with gitleaks
commitsEvery pull requestChecks that every commit is signed off and that no commit message cites an internal tracking reference
imageEvery push to main, so after a mergeBuilds the container, checks what it holds, and drives it with no network: ready within 30 seconds, the API journey, then the ownership and sharing journeys, each seeded on a fresh volume and verified after the container is replaced. ci.yml lists every step.

The browser suite is outside the pipeline. When only a browser can judge your change, run npm run journey:browser yourself, as Development setup describes.

Push the branch to your fork of the repository, or to the repository itself if you can push there, and open a pull request against main. With the GitHub CLI, gh pr create --base main offers to fork and push for you.

The description starts from the project’s template:

SectionWhat you write
What this changesOne or two sentences: what is different after it merges
WhyThe problem it solves, and the issue it closes, such as Fixes #123
How it was checkedThe commands you ran, and what you looked at by eye
For a reviewerA trade-off you made, a place you were unsure, a behavior only a browser shows, and a screenshot if the interface changed
Before you open thisThe sign-off, Conventional Commits, borrowed code in NOTICE, and docs that match what ships

You should see the checks, secrets and commits jobs start on the pull request. On a first pull request from a fork, they may wait until a maintainer approves the run.

Under How it was checked, name each command you ran and read the output of, and say plainly what you did not run.

Give each claim one of these labels. “Verified” on its own is not one of them:

LabelUse it when
confirmedThe code path, a test or a run demonstrates the claim directly
confirmed mechanism, unmeasured impactThe code makes the behavior certain, but how much it matters to a user needs a profile or a reproduction
plausibleReading the code makes it credible, and a concurrency, failure-injection or browser test would settle it
comparative judgmentIt depends on what users expect, or on what another product does

An untested branch of the code stays unverified, however convincing its sibling looks.

A second reader reads the diff before it merges: a person or an agent that did not write the change, starting fresh. Never merge your own pull request without a review.

When an AI agent wrote the change, a maintainer has it reviewed by a model of another family, which shares fewer of its blind spots.

The reviewer reads the change against its description and looks hardest at what its author’s own checking tends to miss:

WhatWhat the reviewer asks
The descriptionDoes the change do what its issue describes, and nothing outside it?
Tests that can failCould each new test fail? An assertion whose two sides come from the same code path, or an absence check against data that never held the value, cannot.
Claims and evidenceDoes the evidence cover every part of the claim? “X and Y each do Z” needs both shown.
ReferencesDoes every path, test, command or script the change names exist?
MeasurementsIs the harness right? A benchmark is code too, and a wrong number is a defect.
The APICan an agent do through the API what a person can do in the app?
Docs and licencesDo the pages match the behavior, and does borrowed code keep its header and its NOTICE line?

Review findings are input, not instructions: each is adopted when it holds up, or declined with a reason on the pull request. Push each fix as a new commit.

Once the checks pass and the review settles, a maintainer merges the pull request with a merge commit. It keeps each of your commits, and the change’s boundary, in the history.

You should see the pull request marked Merged, and the image job start on main, where it builds the container.

The commits job says “Missing Signed-off-by”. A commit lacks the sign-off line. Sign every commit on the branch with git rebase --signoff main, then force-push the branch.

The commits job says a message “carries a planning document number”, “a tracking row identifier” or “a path this repository does not carry”. Reword the commit, writing what the change does instead of the reference, then force-push. For the last commit, run git commit --amend -s -m "<NEW_MESSAGE>"; for an earlier one, git rebase -i main.

npm run lint:citations says a file “cites” something. A tracked file points at a document this repository does not carry. Write the reason in its place, not the reference.

npm test fails with “Authenticated fixtures require a scratch DEZFIL_DATA_DIR” or “DEZFIL_DATA_DIR must name a scratch directory”. The suite needs a scratch folder. Set DEZFIL_DATA_DIR as in step 3.

npm run lint:size says a module is “below its ceiling”. Your change shrank one of the oversized modules. Lower its ceiling to the new line count in scripts/check-monster-files.mjs, in the same change.

Dezfil · Apache-2.0docs from 7439201b