Use this guide when you add or change any file in the repository: code, tests, documentation, diagrams, templates, or data. You learn which license header each format needs, how to explain a Python module, how to declare a file that cannot carry a comment, and how to read the coverage checker's report. It takes about ten minutes to read. You need a source checkout and Python 3.12 or newer; the checker uses only the standard library.
How to read this diagram: Follow the four numbered steps from top to bottom: establish what the code really does, explain it in order, run the checks, and read the result as a reader would. The note at the bottom is why step 4 exists: a passing check proves that the file is attributed and its links work, not that the explanation is right.
First-party source is licensed under the Apache License 2.0 and names the Firefly Software Foundation explicitly. Keep earlier copyright years that still apply, and keep third-party ownership and notices exactly as they are: depending on a library does not transfer its copyright to this project. The complete terms are in LICENSE and NOTICE.
| File | What it needs |
|---|---|
Python, including package __init__.py files, tests, migrations, and scripts |
The # header, then a module docstring that explains the module's responsibility |
Shell, TOML, YAML, INI, CFG, Dockerfile, Makefile, .gitignore, .dockerignore |
The # header; a shebang line stays first |
| SQL | The header with -- comments |
| Markdown, SVG, HTML, XML, and property lists | The header in one <!-- … --> comment at the top, after an XML declaration if there is one |
| TypeScript, JavaScript, CSS, SCSS, and Rust | The header in one /* … */ comment at the top |
Templates ending in .tmpl |
The header for the format the template produces; for example, adapter.py.tmpl is checked as Python, including its docstring |
Strict JSON, lockfiles, images, py.typed, and other formats without comments |
An exact-path entry in the source inventory, as described in step 4 |
| A test fixture whose exact bytes or source positions a test asserts | An immutable-fixture inventory entry with its SHA-256 digest |
Tests, examples, migrations, scripts, and generator templates are source too. When a template generates source, it should emit a header only if the generated format allows comments.
Copy the header exactly; the checker compares every line. This is the Python form, followed by the module docstring:
# Copyright 2026 Firefly Software Foundation.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# Author: Firefly Software Foundation
# SPDX-License-Identifier: Apache-2.0
"""Describe this module's responsibility and its relevant boundaries."""For other formats, keep the same lines and change only the comment syntax. Any
documentation page in docs/ shows the <!-- … --> form, and any file under
studio/src/app/ shows the /* … */ form.
Placement rules. The header must come before any other content:
- A shebang such as
#!/bin/shstays on the first line, with the header right after it. - A Python encoding declaration stays on the first or second line.
- The module docstring comes after the header and before the imports, and
from __future__imports stay where Python requires them. - An XML declaration stays first, with the header comment right after it.
Text inside a string, such as a header printed by a program, does not count. Do not change a signed or hash-checked fixture just to add a header; declare it in the inventory instead.
Every first-party Python module, including package initializers, needs a docstring that explains its responsibility. Describe its public contracts and the invariants a reader cannot see from one function, such as transaction ownership, scope and row-level security, lease fencing, idempotency, concurrency, secret redaction, bounded parsing, and side effects whose outcome can be unknown.
Do not narrate each line or add filler comments to satisfy a check. The checker can only see that a docstring exists; a reviewer judges whether it helps.
Strict JSON, py.typed, lockfiles, images, canonical payloads, and protocol
fixtures cannot hold a comment, and adding a comment field to a wire document
would change its contract. Record their ownership in the
source inventory instead. The inventory keeps their bytes
unchanged.
Each file gets its own [[exceptions]] entry with its exact relative path.
Directory and wildcard entries are rejected. This is a real entry from the
inventory:
[[exceptions]]
path = "examples/worker/manifest.json"
kind = "commentless"
reason = "Strict JSON or canonical fixture; preserve parser contract and exact data bytes."
copyright = "Copyright 2026 Firefly Software Foundation."
author = "Firefly Software Foundation"
license = "Apache-2.0"| Field | Required for | Value |
|---|---|---|
path |
Every entry | The exact path from the repository root, with no wildcards and no .. |
kind |
Every entry | One of the four kinds below |
reason |
Every entry | Why the file cannot carry a header |
copyright |
Every entry | For first-party files, Copyright YEAR Firefly Software Foundation. |
author |
Every kind except third-party |
Firefly Software Foundation |
license |
Every entry | Apache-2.0 for first-party files; the original license for third-party work |
source |
generated and third-party |
The inventoried generator, or the third-party origin |
sha256 |
immutable-fixture |
The file's SHA-256 digest in lowercase hexadecimal |
Choose the kind that matches the file:
commentless: a format that cannot safely carry a header, such as JSON, a lockfile, or an image. The checker rejects this kind for a format that can carry a comment, such as Python or Markdown.immutable-fixture: a test fixture whose bytes or source positions a test asserts. Only files undertests/fixtures/qualify. Any change to the bytes fails the strict check until someone reviews the fixture and updates its digest.generated: deterministic output.sourcemust name the generator, which must itself be in the repository and covered.third-party: preserved external work with its original copyright, license, andsource. Keep the upstream notices, and do not add Foundation authorship.
Most inventory entries are commentless: strict JSON, the Python, npm, and
Cargo lockfiles, and py.typed. Firefly marks (the logo, icon, and lockup
artwork and every file generated from them) are third-party entries with
license = "LicenseRef-Firefly-Marks", and NOTICE states their terms. Two
YAML files are immutable-fixture entries because parser and CLI tests assert
their source positions. generated entries name their generator in source. Examples are
Studio's schema test corpus, produced by
studio_schema_fixtures.py, the shared language
fixtures, produced by language_fixtures.py, and the
worker lockfiles, produced from the pyproject.toml beside each. No vendored
third-party source is declared. Third-party dependencies keep their own
distribution metadata and license terms; the inventory does not certify
redistribution compliance.
From the repository root, run the strict check after every change that adds, moves, or removes a file:
# Report every coverage issue; exit 1 if any remains.
python3 scripts/source_coverage.py --strictExpected: one line per issue in the form PATH: CODE: MESSAGE, then a summary
such as 904 files; 69 excluded entries; 0 issues. The counts grow with the
repository; the last number must be 0.
The checker has three modes:
# Report without failing, for example while you work through a list of issues.
python3 scripts/source_coverage.py
# Write the full report as JSON outside the repository for review or tooling.
python3 scripts/source_coverage.py --format json > /tmp/weave-source-coverage.json
# Fail on any issue, as make check does.
python3 scripts/source_coverage.py --strictExpected: the default mode always exits 0. Strict mode exits 1 when an issue
remains. Both exit 2 with Invalid root/inventory configuration or unreadable source directory. when the root or the inventory cannot be read. A missing
default inventory is allowed for a new tree, but a missing file passed with
--inventory is an error.
What the checker reads, and what it skips. It never imports application code
or modifies a file. It skips version control, private working folders (including
.local/ tutorial output), virtual environments, node_modules, build and
distribution output, browser-test reports, interpreter and tool caches, generated
desktop build output, .env and .env.* files, private .pem and .key files,
operating-system metadata, and the root LICENSE and NOTICE texts. The JSON
report lists each skipped path with its reason; the text report only counts them.
This protects local evidence and conventional secret paths,
but the checker is not a secret scanner or a publication allowlist. It reports
symbolic links instead of following them, and it checks the inventory file and its
parent folders for symbolic links before reading it.
| Code | Why | What to do |
|---|---|---|
missing-header |
The header is missing, incomplete, or not at the very top | Copy the header from step 2 into the file's comment syntax, before any other content |
missing-docstring |
A Python module has no docstring | Add a docstring after the header and before the imports |
python-syntax |
The Python file does not parse | Fix the syntax error; the docstring is checked afterward |
uncovered-format |
The checker does not know how to read a header in this format | Add an exact-path inventory entry, usually commentless |
invalid-exception |
An inventory entry lacks a required field, uses an unknown kind, names a comment-capable format as commentless, has the wrong first-party ownership, or declares an immutable-fixture outside tests/fixtures/ or without a lowercase SHA-256 digest |
Complete the entry using the field table in step 4 |
missing-generator |
A generated entry's source is not a scanned file in the repository, is a symbolic link, or names the entry itself |
Point source at the covered generator |
fixture-drift |
An immutable fixture's bytes no longer match its digest | Confirm the change is intended and the tests still assert the right positions, then update sha256 |
stale-exception |
An inventory entry names a file that no longer exists or is skipped | Remove the entry, or restore the file |
symlink |
The path is a symbolic link | Replace it with a real file, or review the link separately; links are never scanned |
unreadable-source |
The file is not valid text in its encoding | Fix the encoding, or declare the binary format in the inventory |
Do not hide an issue with an invented third-party or generated entry.
The Makefile is the authority for the project checks. make source runs the strict coverage check on its own. make check runs it first,
then the documentation checks, the strict website build, Ruff, strict mypy, the
unit and contract tests, and the release package checks. Integration and
end-to-end suites need separately configured test services; see
contributing.
If you change the coverage checker itself, run its own tests and lint:
# Run the checker's fixture tests.
uv run pytest tests/unit/test_source_coverage.py -q
# Lint and format-check the checker and its tests.
uv run ruff check scripts/source_coverage.py tests/unit/test_source_coverage.py
uv run ruff format --check scripts/source_coverage.py tests/unit/test_source_coverage.pyExpected: pytest reports that every test passed, Ruff prints
All checks passed!, and the format check reports the files as already formatted.
Never publish environment files, credentials, retained test evidence, dependency folders, or temporary build and render output. Review the actual file lists of the published site and the package; ignore rules alone do not prove that a package is safe.
- Build and maintain the documentation website: preview pages and follow the writing conventions.
- Visual assets: draw and check a diagram.
- Contributing: the complete project checks.