Invariants
The margin ended where the final lamp stood, though darkness continued beyond it; measure confesseth its own frontier and therefore remaineth trustworthy within the light.
— Scholia of the Fifth Archive 53:20
This page records behavior that must survive refactoring or replacement of Akashi’s implementation. The Architecture explains how the current code works; this page states what every compatible implementation must preserve.
Severity describes the consequence of violating an invariant:
- critical: Akashi can silently test different code from the maintained documentation or report a false result;
- high: execution can escape its documented boundary, corrupt later tests, or break a supported consumer contract;
- medium: deterministic behavior, diagnostics, or a documented integration becomes unreliable.
Discovery and Identity
| Invariant | Why it exists | Enforcement evidence | Tempting invalid alternative | Severity |
|---|---|---|---|---|
| Includes and exclusions are resolved from one canonical project root, and loaded documents are ordered by slash-normalized project-relative path. | Corpus order and generated identities must not depend on the caller’s working directory or filesystem enumeration order. | MarkdownSourceTest, DocumentationSourceTest, ExampleCorpusTest | Preserve discovery order returned by the operating system. | high |
| Directory discovery does not traverse symbolic links, and one physical document cannot enter a corpus twice. | A configured tree must not escape its boundary or execute duplicate examples through aliases. | MarkdownSourceTest, DocumentationSourceTest | Follow every readable link and deduplicate only the authored spelling. | high |
Every selected fence whose first info-string word is php, case-insensitively, enters the corpus; loading an empty document or example set fails explicitly. | Discovery must not silently hide examples or turn a broken configuration into a green test suite. | CommonMarkExampleExtractorTest, PhpDocExampleExtractorTest, MarkdownSourceTest | Select only marked or conveniently executable fences. | critical |
| PHPDoc extraction inspects every documentation comment, parses only its interior lines, and never associates metadata across comment boundaries. | Declaration attachment and neighboring comments must not silently change which examples or metadata enter the corpus. | PhpDocExampleExtractorTest | Inspect only named declarations or concatenate all comments before parsing. | critical |
PHPDoc external references resolve only to readable .php files inside the canonical project root; repeated references and physical aliases produce one example while retaining all presentation sites. | Canonical code must not escape the selected project or execute more than once because it was documented more than once. | DocumentationSourceTest | Resolve relative to the working directory and execute every reference independently. | critical |
| Named-region markers are standalone tokenized PHP comments with matched unique names; malformed, orphaned, nested, mismatched, duplicate, and empty regions fail. | Guessing region boundaries can silently execute different bytes from the canonical example an author reviewed. | DocumentationSourceTest | Search raw text for the nearest marker or use fragile line-number ranges. | critical |
Generated example IDs are unique within a corpus; explicit example IDs are valid lowercase kebab-case and unique across canonical and configured legacy forms and source formats. | Reports and external extraction must identify exactly one example. | IdentifierTest, ExampleCorpusTest, CommonMarkMetadataTest, DocumentationSourceTest | Let the last duplicate identity win. | high |
| External metadata is associated through CommonMark adjacency; inline metadata is recognized only as PHP comment tokens inside its own code, and every property occurs at most once per example. | Prose, strings, heredocs, unrelated comments, and malformed or conflicting metadata must not change another example. | CommonMarkMetadataTest, PhpDocExampleExtractorTest, DocumentationSourceTest | Search backward or through raw source text with one file-wide regular expression. | high |
Source Fidelity and Transformation
| Invariant | Why it exists | Enforcement evidence | Tempting invalid alternative | Severity |
|---|---|---|---|---|
Example retains unmodified code, one canonical origin, and typed inline or referenced source metadata separately from generated source. | Consumers and diagnostics need the source the author actually maintains and, for references, every distinct presentation site. | CommonMarkExampleExtractorTest, PhpDocExampleExtractorTest, ExampleSourceTest, DocumentationSourceTest | Treat the nearest documentation comment as the maintained code location. | critical |
| Prepared code and its source map have equal line counts; a generated line maps to a maintained documentation line or explicitly has no exact mapping. | Failures must not report a plausible but incorrect location. | TransformValueTest, PhpUnitResultAsserterTest, RuntimeConformanceTest | Apply text edits without updating locations. | critical |
| In-process preparation uses the fixed parse → name-resolution → safety-validation → assertion-rewrite → namespace-isolation order. | Reordering changes name meaning, safety decisions, and diagnostic locations. | InProcessTransformerTest, NativeAssertionRewriteTest, InProcessSafetyValidatorTest | Expose independent transforms that callers may reorder. | critical |
| Unsupported relocation or process-state behavior is rejected explicitly; Akashi never silently changes an example’s requested backend. | A passing result under weaker or different semantics would be false evidence. | InProcessSafetyValidatorTest, PhpUnitRuntimeTest | Automatically reroute anything difficult or ignore unsafe syntax. | critical |
Supported in-process native assert() calls always execute and preserve the authored expression and optional message. | Documentation assertions must not disappear under zend.assertions=-1. | NativeAssertionRewriteTest, NativeAssertionTest | Delegate to native production assertion configuration. | high |
Execution
| Invariant | Why it exists | Enforcement evidence | Tempting invalid alternative | Severity |
|---|---|---|---|---|
| In-process is the default; an authored separate-process directive takes precedence and requires explicit runtime configuration. | Backend selection must be predictable and requested isolation must not be weakened. | PhpUnitRuntimeTest, RuntimeConformanceTest | Fall back to in-process when child configuration is missing. | high |
| Compile-only examples are parsed with maintained source locations but do not select a backend, transform, bootstrap, or execute code. | A non-running example must not gain side effects merely to establish syntax evidence. | PhpUnitRuntimeTest | Execute the example in a child and call that compile-only. | high |
| Expected stdout compares captured bytes exactly only after execution or the expected-exception contract succeeds; empty output remains an explicit valid expectation. | Output evidence must not be normalized, confused with absence, or allowed to mask a primary runtime failure. | PhpUnitResultAsserterTest, PhpUnitRuntimeTest | Trim output, normalize line endings, or report output mismatch before a wrong throwable. | high |
| In-process execution uses an empty local scope, captures output, and attempts to restore guarded working-directory, error-reporting, and output-buffer state even after failure. | One example must not accidentally inherit caller variables or poison later tests. | InProcessExecutorTest, InProcessStateGuardTest | Restore state only after successful execution. | high |
| Separate-process execution uses an explicit argument vector without constructing a shell command, private temporary files, the configured project root, and a finite timeout; cleanup runs on every outcome. Expected throwables use validated private evidence rather than stderr parsing. | Child execution must resist command injection, preserve trustworthy typed exception evidence, and avoid leaving source or evidence behind. | SubprocessExecutorTest, PhpUnitRuntimeTest | Build a shell command string, scrape stderr for a type, or use a predictable shared temporary file. | critical |
| Execution returns one typed success or failure variant, preserving the first cause, phase, captured streams, duration, mapped line, and any cleanup failures. | Reporting must not erase the primary failure or hide a damaged cleanup boundary. | ExecutionResultTest, PhpUnitResultAsserterTest | Throw away structured evidence and keep only one message. | high |
Neither backend is a security sandbox. The compatibility reference defines external effects and fatal conditions that remain outside these isolation invariants.
Verification, CLI, and Boundaries
| Invariant | Why it exists | Enforcement evidence | Tempting invalid alternative | Severity |
|---|---|---|---|---|
PHPStan expectations are parsed in authored order and match diagnostics by exact count plus a deterministic one-to-one assignment. Identifier expectations also require an exact identifier and a diagnostic line within the associated statement; legacy //! expectations retain example-wide substring matching. | Greedy, partial, identifier-blind, or location-blind matching can accept the wrong diagnostic set. | ExpectationParserTest, DiagnosticMatcherTest, PhpStanConformanceTest, VerifiesPhpStanExamplesTest | Accept any diagnostic containing each substring, reuse diagnostics, or ignore the statement that an identifier directive annotates. | critical |
| PHPStan verification validates the complete selected declaration set before loading it and restores process state and temporary files afterward. | A late collision or define() can fatally pollute the hosting test process. | VerifiesPhpStanExamplesTest | Require examples one at a time and discover conflicts after mutation. | high |
Successful extraction writes only the original example plus its final-LF contract to stdout; diagnostics use stderr; statuses remain 0, 1, 2, and 70. | Consumer scripts need byte-stable output and machine-stable outcome categories. | CliConformanceTest (public streams and statuses 0, 1, and 2), ApocryphaCompatibilityTest (consumer-compatible extraction bytes), ExitCodeTest (all status values, including 70) | Mix progress text with extracted PHP or infer failure categories from prose. | critical |
| Synchronization write mode validates the complete selected set before mutation, refuses stale maintained bytes and symbolic-link paths, rejects changing selected whole-file canonical dependencies, and atomically replaces each changed document from a flushed sibling. | A partial document, overwrite of newer/unintended bytes, or replacement calculated from a canonical file that the same batch changes would corrupt or immediately stale the maintained documentation. | ApplicationTest, SynchronizationWriterTest | Resolve selected aliases after losing their spelling, truncate files in place, continue from a stale snapshot, or compute every replacement from the initial batch state. | critical |
| Formatter checking sends only inline examples through an argument-vector PHP-CS-Fixer process, verifies its protected body boundary, maps evidence to maintained source, and cleans private temporary input on every outcome. Its pure rewriter accepts only current mismatches for one document, changes exact code spans, and re-extracts the candidate before returning it. Check mode never writes; write mode repeats every formatter before using stale-byte-protected, symbolic-link-rejecting atomic replacement. | Project header rules, malformed formatter output, shell interpolation, leaked temporary source, nondeterministic formatting, or stale/cross-document replacements must not corrupt a fence or hide which documentation failed. | FormattingCheckerTest, FormattingRewriterTest, ApplicationTest, CliConformanceTest, composer test:phpunit10 | Run a shell command over the documentation file itself, trust every byte returned around the example body, or write a stale document without structural validation. | high |
| PHPUnit 10.5/11.5 and PHPStan 1.12/2.x remain optional integration dependencies, and every Akashi declaration is explicitly public or internal without exposing internal types through public signatures. | Core discovery and the CLI must autoload independently, while compatibility obligations remain reviewable. | PublicApiBoundaryTest, PackageMetadataTest, composer test:phpunit10, composer test:phpstan1 | Let autoloadable classes become public accidentally or leak integration types into core. | high |
Consumer-specific snapshots under tests/Fixtures/Compatibility supplement these invariants. They record real
acceptance evidence, while tests/Conformance exercises the supported public boundaries without depending on another
checkout.