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>
8.0 KiB
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, remoteproductionbranch, 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.tomlproject.version, currently1.0.x). The running app reads it live at boot (DevPlace:config.APP_VERSIONviatomllib), 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 bygit config core.hooksPath .githooksin 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">inbase.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-yearmax-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
productionbranch (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 --hardon 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):
- 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. - Bottom of the file is a
Doc historytable with one row per version: version, date, one-line change note. - 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.
- The version bump and the content change ship in the same commit,
so
git log -p <doc>and the history table always agree. - Cross-doc references name the section, not the version ("see
quality_software.mdsection 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
- Single version source read live by the app; pre-commit hook auto-bumps patch; minor/major are manual release commits.
- Asset URLs carry
{version}-{boot-id}, served immutable; proxy regex accepts the full version alphabet. - Trunk
master, ticket branches,productionpromotion target, CI gate on master, no history rewrites, hooks in-repo. - Every
.mdstarts with thedoc:version comment and ends with a history table; every update bumps; CI verifies the header. - Terms, SLA, pricing, and API contracts are versioned docs with citable versions, not wiki pages.
- 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. |