Files
devplacepy/quality_versioning.md
T
retoorandClaude Sonnet 5.5 f55c7ee5f4
DevPlace CI / test (push) Failing after 31m42s
Add community node protocol spec, Agent Skills, and make the failing tests hermetic
Community nodes (Phase 1 of plan.md): the protocol specification in
services/nodes/spec.py as the single source of truth, GET /nodes/spec.json,
a generated protocol docs page, the Community nodes API docs group, and the
implementation plan plus the residential proxy research. The no-open-proxy rule
is enforced in the spec (open_proxy cannot be set).

Agent Skills: register the Skills API docs group, cascade skills on account
deletion, add the nested CLAUDE.md, README and routes docs, and cover the
parser, the fetcher (end to end against a mock origin), the data layer and the
routes with 73 unit and 16 api tests.

Tests made hermetic with the repo's existing patterns instead of ambient
environment: embeddings tests set OPENROUTER_API_KEY via monkeypatch, the
workspace tests install FakeBackend via runtime.set_backend, and the skills
install tests use run_async. DockerCliBackend now returns 127 (command not
found) when the CLI is missing instead of raising FileNotFoundError, so a host
without docker answers with a clean error rather than a 500. The Providers tab
empty state no longer names the Model routes tab.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-14 07:13:25 +02:00

166 lines
8.0 KiB
Markdown

<!-- doc: quality_versioning.md | version: 1.0.0 | updated: 2026-10-11 -->
# Quality Versioning Playbook: App, Assets, Docs, and Git
Generic companion to `quality_software.md`. It covers how DevPlace
versions its application, its static assets, and its git history,
plus the one practice DevPlace does NOT have today and you should
adopt from day one: versioned markdown docs.
Honest baseline (researched 2026-10-11, do not assume otherwise):
- App version: single source `pyproject.toml`, auto-bumped patch on
every commit by a checked-in pre-commit hook. Real and working.
- Asset version: composed `{APP_VERSION}-{BOOT_ID}`, stamped into
every static URL, served immutable. Real and working.
- Git: trunk `master`, remote `production` branch, per-ticket
branches, CI gate on push/PR to master. Real and working.
- Tags: none. Changelog file: none. Markdown versioning: none.
These are gaps, and sections 4 and 6 below define what to do
instead of copying the gap.
## 1. App versioning: one source, auto-bumped
- One file owns the version (DevPlace: `pyproject.toml`
`project.version`, currently `1.0.x`). The running app reads it
live at boot (DevPlace: `config.APP_VERSION` via `tomllib`), so
the version in code and the version on disk can never drift.
- A checked-in pre-commit hook bumps the patch number on every
commit (DevPlace: `.githooks/pre-commit`, activated by
`git config core.hooksPath .githooks` in the install target).
Skips merge commits and commits that already touch the version
line, so a manual minor/major bump is never double-bumped.
- Semver discipline: patch is automatic (every commit), minor is a
manual commit when a user-visible feature lands, major is a
manual commit on breaking change. Minor/major bumps are ordinary
commits whose message says what the release contains.
- The version is visible at runtime: stamped into a meta tag
(DevPlace: `<meta name="asset-version">` in `base.html`) so any
page view, bug report, or screenshot names the exact build.
Hosting example: the control panel footer and every support ticket
show `v2.14.3`; support never asks "which version are you on".
## 2. Asset versioning: cache forever, deploy instantly
- Compose the asset version from app version plus boot id:
`STATIC_VERSION = {APP_VERSION}-{BOOT_ID}` where the boot id is a
deploy-provided marker with a wall-clock fallback.
- Stamp it into every app-owned static URL
(`/static/v<version>/...`) through one URL helper, and serve that
path immutable with a one-year `max-age`.
- Keep the reverse proxy in sync: the versioned-path location regex
must accept dots and hyphens, not digits only, or the immutable
header silently stops applying (this was a real production bug
class here, fixed once the version segment stopped being a bare
timestamp).
- Never hardcode a static path; every template and script builds
URLs through the one helper, so a version-shape change touches
one function.
## 3. Git workflow: trunk, tickets, production
- Trunk is `master`. All work lands there through small commits;
CI (serial full suite, coverage, failure screenshots) runs on
every push and PR to master and must be green before merge.
- One branch per ticket or task, named after the tracker
(`ticket-123`, `112-short-slug`). Short-lived: branch, commit,
merge, delete. No long-running feature branches.
- One `production` branch (or tag set, see section 6) marks what is
deployed. Development happens on master; promotion to production
is a deliberate merge, followed by deploy and live verification.
- Commit messages: imperative summary line under 72 chars, blank
line, body explaining why (not what, the diff shows what).
Optional trailers for attribution (`Co-Authored-By`) and session
links. Reverts say what behavior returned and why.
- Never rewrite published history: no amend/push-force, no rebase
of shared branches, no `reset --hard` on anything pushed. Fix the
working tree forward; a mistaken commit is corrected by a new
commit.
- Hooks live in the repo (`.githooks/`) and are wired by the
install target, so every clone gets the version bump and any
future checks with zero manual setup.
## 4. Markdown versioning: every doc carries its version
This is the rule DevPlace does not follow yet: **every markdown
file is versioned on every update.** Adopt it from the start; it
costs one line per edit and buys traceability for every claim a
doc makes.
Scheme (copy literally):
1. First line of the file is an invisible HTML comment:
`<!-- doc: <filename> | version: X.Y.Z | updated: YYYY-MM-DD -->`
It renders nothing and survives every markdown renderer.
2. Bottom of the file is a `Doc history` table with one row per
version: version, date, one-line change note.
3. Doc-semver: MAJOR for restructure or section renumbering, MINOR
for a new section or new rule, PATCH for wording, fixes, or
example updates. Every update bumps exactly one level and adds
exactly one history row.
4. The version bump and the content change ship in the same commit,
so `git log -p <doc>` and the history table always agree.
5. Cross-doc references name the section, not the version ("see
`quality_software.md` section 9"), so minor doc bumps never
cascade into other files.
Enforcement options, cheapest first: a pre-commit check that fails
when a staged `.md` lacks a matching version-line change (same
pattern as the app-version hook, inverted: docs must be touched by
hand, so the hook only verifies); a CI grep that every tracked
`.md` starts with the `doc:` comment; a unit test listing tracked
markdown files and asserting the header parses.
Hosting example: `docs/sla.md` at `3.1.0` and `docs/pricing.md` at
`5.0.2` evolve independently; a customer dispute cites "SLA v3.1",
not "the docs, at some point".
## 5. What gets a version vs what gets a timestamp
- Versioned (semver, comparable, citable): the app, each markdown
doc, API contracts, terms/SLA/pricing pages, database export
formats, agent tool catalogs.
- Timestamped (point-in-time, never compared): deploys (boot id),
backups, audit events, usage ledger rows, generated reports.
- Never versioned alone: a bare counter with no history row, a date
with no change note. A version you cannot diff is decoration.
## 6. Releases and tags: close the gap deliberately
DevPlace has no tags and no changelog file; promotion is tracked by
the `production` branch. For a hosting company, where customers and
auditors ask "what changed and when", close this gap:
- Tag every production promotion with an annotated tag
(`v2.14.0`, message = release notes summary). Tags are cheap,
immutable pointers; the branch can move, the tag cannot.
- Keep one `CHANGELOG.md` (itself doc-versioned per section 4)
with one entry per minor/major release: date, tag, added,
changed, fixed, security notes. Patch releases batch into the
next minor entry; no per-commit changelog spam.
- Release flow in order: land feature commits on master (CI green),
manual minor/major bump commit, merge master into production,
tag, deploy, verify live, write the changelog entry. A release
that is not verified live is not released.
## 7. Replication checklist for your hosting site
1. Single version source read live by the app; pre-commit hook
auto-bumps patch; minor/major are manual release commits.
2. Asset URLs carry `{version}-{boot-id}`, served immutable;
proxy regex accepts the full version alphabet.
3. Trunk `master`, ticket branches, `production` promotion target,
CI gate on master, no history rewrites, hooks in-repo.
4. Every `.md` starts with the `doc:` version comment and ends with
a history table; every update bumps; CI verifies the header.
5. Terms, SLA, pricing, and API contracts are versioned docs with
citable versions, not wiki pages.
6. Annotated tags plus one changelog for customer-facing releases;
release = merge, tag, deploy, verify live, changelog entry.
## Doc history
| Version | Date | Change |
|---------|------|--------|
| 1.0.0 | 2026-10-11 | Created from repo research: app auto-bump hook, asset composition, trunk/ticket/production git model, new markdown-versioning scheme. |