Repository navigation
Development
composer test # PHPUnit — 214 tests, 679 assertions
composer stan # PHPStan level 6, strict types
composer check # both
php tools/build-manifest.php # regenerate config/manifest.json (release step only)Tests live in tests/Unit and tests/Feature and run against a throw-away project root
(tests/TestCase.php); no test touches real storage or content. Security behaviours (path traversal,
XSS vectors, CSRF) and the historic v2 bugs (Unicode filenames, em-dashes, fence-length nesting) have
dedicated regression tests.
pwsh -NoProfile -File tools/Invoke-ProjectDoctrine.ps1Checks over the project's own conventions (version carriers, manifest freshness, sanitizer allowlist shape, cache key content, admin page registration, wikilink contract and more). Baseline at 3.5.0 on PHP 8.5.12: 0 errors, 0 warnings (12 checks). A red run is a real finding — but compare with the baseline before blaming your change.
.github/workflows/ci.yml runs on every push: PHP 8.5 only — lint, PHPStan, PHPUnit and the
smoke requests; plus a frontend build reproducibility job (a difference is reported, not fatal).
- Bump
src/Core/Version.php(VERSION,CODENAME). -
cd tools/frontend && node build.mjs --vendor— refresh assets. -
composer checkgreen andtools/Invoke-ProjectDoctrine.ps1at the baseline. - Build the release tree from the tag in a clean copy, then
composer install --no-dev --optimize-autoloader— the archive shipsvendor/so an install needs no Composer on the host. -
php tools/build-manifest.phpin that same tree and copyconfig/manifest.jsonback into the repository. The updater verifies every file in the archive against the manifest embedded in it and refuses the whole update on the first mismatch. - Zip the tree (everything except
storage/*contents,tools/frontend/node_modulesand.md.ini) asMD.Scribe-<version>.zip. - Update
CHANGELOG.mdand the README badges; commit. - Tag
v<version>, create the GitHub release and attach the archive — the updater downloads the release asset, not a branch tarball. - Deploy the release to a real host and run the checks in Getting started and Updates before telling anyone it works.
-
vendor/composer/installed.phprecords the git reference of the build, so rebuilding an old archive fromgit archive(no.git) changes that one file's hash. Build releases from a checkout, not from an extracted archive. - The manifest must be regenerated after the version bump and in the tree that will be zipped; a manifest regenerated in the working tree silently describes files that no longer match the archive.
bin/md-scribe-render (the standalone CLI renderer:
bin/md-scribe-render README.md --html --toc > page.html
bin/md-scribe-render - --json < notes.md) is deliberately not in PHPStan's paths and not in the CI lint list. The price is paid by hand:
php -l bin/md-scribe-render before editing, and a smoke run after. Everything else — src,
public, templates, tools, tests and the three root scripts — is linted, and src is analysed
at level 6.
- Add it to
config/defaults.phpwithtype,default,section,labelanddescription. - Read it through
Config(bool(),int(),str()) — never read.md.inidirectly. - Add the smoke expectation to the doctrine checker if the key changes a contract.
MD.Scribe 3.5.0 "Loom" · PHP 8.5 (verified on 8.5.12) · MIT · repository · releases