Repository navigation
feat(core): add the gatepost/postcode core with its checks and CI - #1
Merged
Merged
Conversation
composer check runs every tool in Part A of php.md, so a contributor and CI run the same command. The core is empty until the next tasks add it, test first. Signed-off-by: MobileMage <aidelojejoshua@gmail.com>
The ban lists missed the clock classes, require_once and most of intl, the coverage floor ignored classes that no test loads, and nothing checked the PSR-4 layout. The hook now also needs a sign-off and rejects an AI co-author line. The repo standard lists the newer PHP features that only the PHP 8.1 CI job can catch. Signed-off-by: MobileMage <aidelojejoshua@gmail.com>
The spec now names Unicode 17.0 as its NFKC baseline and says what parse, isLegacy and normalize do with text that is not valid UTF-8, which the PHP package needs. Its vectors also use NIPOST's codes for five states. Signed-off-by: MobileMage <aidelojejoshua@gmail.com>
A checked generator writes the spec values into SpecData, so no value is copied by hand (CS-4) and a Packagist install, which has no submodule, still holds them. Signed-off-by: MobileMage <aidelojejoshua@gmail.com>
composer check ran only the passing path of the generator, so a check that always passed would go unseen. New tests run the generator and the loader on bad data. The readers now check the shapes that their comment promises, missing files give one clear message, and a term that could never change the result of precisionForAccuracy is gone. Signed-off-by: MobileMage <aidelojejoshua@gmail.com>
PHP has NFKC only in ext-intl, which many hosts lack (PHP-9). The table holds every character whose NFKC form can be part of a postcode, so parse gives the same result as with a full NFKC. ADR 0002 records the trade-off. Signed-off-by: MobileMage <aidelojejoshua@gmail.com>
The NFKC table comes from the Unicode Character Database, whose licence asks that its notice stay with copies of the data. The generator now writes the Unicode copyright and licence into the table's header, and NOTICE names it. The generator also checks a download before it caches it, so a broken download no longer blocks later runs. New tests pin astral characters in normalize and each half of the fix-table checks. Signed-off-by: MobileMage <aidelojejoshua@gmail.com>
The input limit costs one strlen call for long text and one short PCRE call otherwise, so a large form field cannot stall a server. Text that is not valid UTF-8 gives an error code and no exception, as Proposal P1 in the plan describes. Signed-off-by: MobileMage <aidelojejoshua@gmail.com>
The spec now has a plain reading of its grammar that checks every vector, and new vectors for astral characters, for NFKC forms that hold a dash, for a digit at the start of the area and for an accuracy of -0. The glossary drops a claim about NIPOST that no public source supports. Signed-off-by: MobileMage <aidelojejoshua@gmail.com>
Text that is not valid UTF-8 gives bad_character up to 4 bytes for each code point of the input limit, and bad_length above it. No test held text between 65 and 256 bytes, so a check that counted bytes against the limit itself passed every test. Two rows now pin table entries whose NFKC form is a dash. Signed-off-by: MobileMage <aidelojejoshua@gmail.com>
A user who types O for 0 in an LGA gets one hint that parses, and never a silent change. The district stays as typed, because NIPOST has not confirmed its characters. Signed-off-by: MobileMage <aidelojejoshua@gmail.com>
check-tells now reads more kinds of file, such as phpunit.xml.dist, phpstan.dist.neon and infection.json5, and it can check the message that a squash merge puts on main. The spec also adds two vectors for a letter after a digit in the LGA and in the unit. Signed-off-by: MobileMage <aidelojejoshua@gmail.com>
The glossary avoids the word part for a segment, so the code now says segment. A comment also says why the suggestion parse stops after one nested call: a fix table never writes a character that it changes. Signed-off-by: MobileMage <aidelojejoshua@gmail.com>
Apps cut a code to the precision that a GPS fix supports, and logs need the redacted form (ERR-3). Truncate and parent read the segment ends from the spec data, so no precision order is copied by hand. Two unit tests cover what the vectors miss. One checks the compact form and the precision of a truncated code. The other checks that contains does not find a state in a later segment. Signed-off-by: MobileMage <aidelojejoshua@gmail.com>
contains() and parent() rest on facts that their code does not show: each precision has a fixed length, and the spec data lists the segments from the least precise. Two comments now say so. A truncate vector that expects an error now fails with the right message when no error comes. Signed-off-by: MobileMage <aidelojejoshua@gmail.com>
PHP has no standard property-testing tool, so a seeded generator checks the rules that must hold for every input, such as a parse that never throws. Signed-off-by: MobileMage <aidelojejoshua@gmail.com>
The spec adds vectors that pin each segment of a contains prefix, long input to normalize, and each lower-case ASCII letter, and its text now lists the rules that each SDK tests itself. Signed-off-by: MobileMage <aidelojejoshua@gmail.com>
A review planted mistakes that every property passed: a case table without one letter, a canonical form with one hyphen, and a parse that throws on random text. Each property now checks the result in full, the typo list comes from the spec data, and a failed run shows its input. Signed-off-by: MobileMage <aidelojejoshua@gmail.com>
DOC-2 and DOC-3 ask for a README that follows the template, with examples that CI runs. ReadmeTest runs each PHP example and compares its output. It also checks that the input limit in the text equals the limit in the spec data, so a stale example or number fails the build. ADR 0001 records why the package keeps PHP 8.1 as its floor after the end of life of that release, with the WordPress.org usage numbers of 2 Oct 2026, as VER-1 asks. Signed-off-by: MobileMage <aidelojejoshua@gmail.com>
DOC-5 asks for a changelog that change files generate. Changie wrote this entry from one change file for the offline core of spec 0.1.0. The release tag comes after the branch merges, so this commit adds no tag. Signed-off-by: MobileMage <aidelojejoshua@gmail.com>
CI runs composer check on PHP 8.4. It runs the tests on PHP 8.1 and on the newest PHP release with ext-intl off, because the standards ask for both versions and PHP-9 forbids a need for that extension. A pull request workflow checks the sign-off of each commit and the message that the squash merge writes. Scheduled workflows run the mutation tests, CodeQL and Scorecard. SEC-6 asks for pinned actions, so composer check now runs zizmor, and the licences check pins its encoding detector as well. The contributor notes now say how to add a missing sign-off, because the sign-off job fails on it. Signed-off-by: MobileMage <aidelojejoshua@gmail.com>
Renovate opens one pull request each week for the Composer packages, the digests of the GitHub Actions and the versions of the tools that composer.json and the workflows pin. Its commits and the end of its pull request bodies carry the sign-off that the pull request workflow needs, and its titles use the chore(deps) form. The file stays out of the Packagist archive. Renovate runs only after the owner installs its app. Signed-off-by: MobileMage <aidelojejoshua@gmail.com>
|
You are seeing this message because GitHub Code Scanning has recently been set up for this repository, or this pull request contains the workflow file for the Code Scanning tool. What Enabling Code Scanning Means:
For more information about GitHub Code Scanning, check out the documentation. |
Composer installs only stable releases by default, so the old install line failed while the only release is an alpha. The README now gives a constraint that allows it, and it drops a claim about commit bodies that no check enforces. CI also runs the quickstart without the dev packages, whose polyfills could hide an intl call, and the API check no longer compares a release with an older alpha. Signed-off-by: MobileMage <aidelojejoshua@gmail.com>
T-2 and PAR-1 ask that every vector file runs, and nothing checked it: a file added to spec/vectors passed CI with no runner. VectorFile now keeps one list of the file names, and a test compares the list with the folder and with the runners. DEP-4 asks for a permissive licence in each dependency, and no tool read the licences. scripts/check-licences.php reads composer.lock and the lock file of each project in tools, applies the licence list of the js repo, and fails on a lock that is missing, broken or empty. NPG-5 asks for an API dump before the first release. scripts/dump-api.php lists the public symbols of src by reflection into docs/api-dump.md, and composer check fails when that file is out of date, which also enforces GIT-7. AGENTS.md names the file. The tests of these scripts share one helper for temporary folders. Signed-off-by: MobileMage <aidelojejoshua@gmail.com>
The generator now stops on a state code, a segment name or a separator that appears twice, because the generated array would keep only the last one and hide the mistake. A syntax error in a data file names the file, and a file that no user can read gives the clear message in place of a PHP warning. PortabilityTest bans more names for file access, the environment, the network, the clock and randomness, and it reads a string such as 'Normalizer::normalize' as a callable. It skips a method or a property that only shares its name with a function. ComposerRequireChecker does not replace the lists. It flags only the symbols of extensions that composer.json does not require, and it reads no string, so it misses fgets, unlink, mkdir, getenv and each string callable. GIT-3 now refuses a co-author line by the address of the AI tool, so a person named Claude can co-author a commit. Two more coverage fixtures pin the boundary of the complexity check in check-coverage.php: a class of constants must pass, and a class with one path must fail. Signed-off-by: MobileMage <aidelojejoshua@gmail.com>
DOC-3 asks that CI runs each code example. DocExamplesTest runs the php examples in the doc comments of src, which the README names as the API reference until the docs site is live, and it compares each result that an example shows. ReadmeTest now checks that the install constraint allows the newest changelog version, with composer/semver, because the stability flag alone passed a constraint that Composer would not match. The multiline test joins the input limit tests, and the limit of PHPMD on public methods splits those tests by concept into InputLimitTest and InvalidUtf8Test. One TemporaryFolder helper replaces two ways to make and remove a temporary folder. The words follow the glossary: normalize says Normalises, the property tests say legacy postcode, and BadLength says what parse does with the length. AGENTS.md repeats the line of the spec template about the spec folder, the changelog entry names the nine functions of the first release, and the comment in PropertiesTest gives its reason without a measured time. Signed-off-by: MobileMage <aidelojejoshua@gmail.com>
The new matcher of PortabilityTest ran one pass over src for each list of names. Under Xdebug path coverage, that added about 35 seconds to the tests of composer check. The test now builds one lookup from all the lists, reads each file once, and checks a token against the lookup only when it can hold a name. The planted code tests give the same results as before. Signed-off-by: MobileMage <aidelojejoshua@gmail.com>
PHP 8.5 reports the class name for a type written self, and PHP 8.1 to 8.4 report self, so the tests job failed on 8.5. The dump now writes self for the declaring class and parent for its parent class, so the file does not depend on the version. A fixture method that names its own class reproduces the 8.5 spelling on any version. A test checks the committed dump, so the tests job covers it on each PHP version. The script was 487 lines. The functions that write a symbol are now in scripts/dump-api-symbols.php, which the entry point requires, as generate-data.php does with its helpers. Signed-off-by: MobileMage <aidelojejoshua@gmail.com>
GIT-3 read only exact addresses, so Claude <claude@anthropic.com>, the GitHub address of Claude Code, copilot@github.com and Gemini Code Assist passed, and the old word list had refused the first three. The check now refuses each address at anthropic.com and openai.com, and adds the three addresses that other tools write. A person named Claude at another domain still passes. The row for a person at an AI company is gone, because the rule now refuses that address. Signed-off-by: MobileMage <aidelojejoshua@gmail.com>
The string check counted a bare word such as copy, system or rand as a banned name, so a message in src with such a word would fail the test. A bare string now counts only when its word is not on a short list of common words. A string that names a method of a banned class, such as 'Locale::getDefault', and a string with an uncommon function name, such as 'strtoupper', still count. The test cannot tell where a callable goes without tracking calls, so the common words in a callable string are not caught. Signed-off-by: MobileMage <aidelojejoshua@gmail.com>
A file that exists but that no user can read passed is_file(), so file_get_contents() printed a PHP warning before the clear message, or no clear message at all. The vector loader, the generator, the NFKC table loader, the API dump check and the coverage check now test is_readable() first. A test gives the vector loader a file with no read access, and the others use the same one-line test. Signed-off-by: MobileMage <aidelojejoshua@gmail.com>
MobileMage
marked this pull request as ready for review
October 2, 2026 21:59
The spec branch is merged. Its squash commit on main, tagged v0.1.0, holds the same files as the commit that the submodule named before. Signed-off-by: MobileMage <aidelojejoshua@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
gatepost/postcode parses, checks and formats Nigeria's digital
postcodes in PHP, with no network access. It implements spec 0.1.0:
normalize, parse with typo suggestions, isLegacy, truncate, parent,
contains, redact, stateName and precisionForAccuracy. It runs on PHP
8.1 and later, without the intl and mbstring extensions. A generated
table holds the NFKC forms that a postcode can use, from the Unicode
Character Database 17.0.0, and a generator writes the spec data into
the package.
Every shared vector runs in the tests, with seeded property tests and
a weekly mutation run. CI runs composer check on PHP 8.4, and the tests
on PHP 8.1 and 8.5 with ext-intl off. It also checks the squash
message, the sign-off of each commit and the workflow pins.
This change is larger than the 400 lines that GIT-5 suggests, because
it starts the package. Most of it is tests, generated data and tool
configuration. src/Postcode.php passes the 300 lines that CS-3
suggests: about 140 of its 320 lines are the doc comments and examples
that DOC-1 asks for, and a split would add a layer that only forwards
calls (API-12).
Signed-off-by: MobileMage aidelojejoshua@gmail.com