13 KiB
Changelog
All notable changes to indifferentketchup/codex are documented here.
The format follows Keep a Changelog and this project adheres to Semantic Versioning.
[Unreleased]
0.3.0 — 2026-05-04
Adds IP-address redaction to the PZ redactor, a new ErrorContextAnalyser for surrounding-context surfacing, the tools/pz-analyzer/ Python toolset (pre-production Qwen-driven research analyser and production-bound deterministic classifier), and a parser fix for the PZ B42 log shape that was silently breaking level/prefix attribution since The Indie Stone dropped the per-line t: field. New public API surface across the redactor and the analyser-side classes makes this a minor bump rather than a patch.
Added
- IP redaction in
ProjectZomboidRedactor(src/Util/ProjectZomboid/ProjectZomboidRedactor.php) — fourth pass that scrubs IPv4 (strict 0-255 octets, optional:portsuffix) and IPv6 (full, abbreviated, bracketed-with-port, IPv4-mapped) addresses, replacing them with the literal[REDACTED_IP]. New public API:IP_REPLACEMENT,IPV4_REGEX,IPV6_REGEXconstants and aredactIpAddresses(bool)toggle (defaults on, mirroring the existing three category toggles). Pattern-disjoint from the Steam-ID → name → coordinates chain; runs first by convention. Strict regexes plusfilter_var()validation prevent false positives on PZ timestamps and PHP / Java scope ops. 20 new unit tests across two files (ProjectZomboidRedactorIpv4Test.php,ProjectZomboidRedactorIpv6Test.php). ErrorContextAnalyser(src/Analyser/ProjectZomboid/ErrorContextAnalyser.php) — generic-purpose analyser that walksEntry[]once and emits oneErrorContextProblemper ERROR / WARNING entry with up toCONTEXT_BEFORE(20) entries of leading context andCONTEXT_AFTER(20) entries of trailing context. Overlapping windows clip tolastEmittedIndex + 1so no Entry appears in two context arrays; emission caps atHIT_CAP(500) with a singleErrorContextTruncatedInformationappended when reached. Standalone — not auto-registered to any existing Log subclass'sgetDefaultAnalyser(); consumers wire it in explicitly. Companion classesErrorContextProblemandErrorContextTruncatedInformationundersrc/Analysis/ProjectZomboid/. 3 unit tests, 134 assertions.tools/pz-analyzer/— Python toolset adjacent to the library (not part of the Composer package's autoload surface).pz_redact_all.shis a one-shot Docker wrapper that runs the PHP redactor over.scratch/pz/Logs/and produces a gitignored.scratch/pz/Logs.redacted/directory.pz_error_analysis.pyis a developer-facing Qwen-backed pre-production analyser that calls a local OpenAI-compatible endpoint to classify residual log shapes the deterministic side hasn't yet captured.pz_parser.py+pz_classify.pyare the production-bound deterministic-only counterpart: pure parser module with mod attribution, file:line extraction, cause-chain unwinding, engine-noise tagging, and a two-level signature scheme (pattern_id+signature), plus a stdlib-only orchestrator that walks the redacted directory and emits a JSON report. 32 Python unit tests across three files, 16 synthetic fixtures.docs/superpowers/specs/2026-05-04-pz-deterministic-classifier-design.md— design contract forpz_parser.py/pz_classify.py. The PHP-sideErrorContextAnalyserships without a separate spec; its design fell out of a brainstorming session inline with the pzmm-pattern-port discussion.- New synthetic fixture
test/src/Games/ProjectZomboid/fixtures/debug-server-42x-minimal.txtmirroring the existing B41 fixture in PZ B42 line shape.
Changed
DebugServerPattern::LINEregex relaxed to handle PZ build 42.x. The Indie Stone dropped the per-linet:(microsecond) field and tightened the spacing betweenf:N,t:N, andst:N,N,N,N>markers somewhere on the way to build 42.17. The previous regex required the fullf:\d+,\s+t:\d+,\s+st:triplet and silently failed on every B42 line. Now(?:,\s+t:\d+)?makes thet:N,field optional and,?makes the inter-field comma optional. Backwards-compatible — every B41 line continues to parse identically.ProjectZomboidServerLogTestnow runs each parser-shape assertion via#[DataProvider]against both fixtures.- Pass order in
ProjectZomboidRedactor::redact(): the new IP pass runs first, so the chain is nowIP → Steam ID → player name → coordinates. The mandatory Steam ID → name → coordinates ordering is preserved; placement of the IP pass is by convention since its regexes are pattern-disjoint from the rest. CLAUDE.mddocumentsiblogsas the primary downstream consumer with a per-component checklist for cross-repo public API impact; the release-flow cadence; the feature-branch workflow set by theredactorandiblogs-bootstrapprecedents; and thedocs/superpowers/specs|plans/path convention..gitignoreexcludes__pycache__/(Python bytecode caches generated undertools/pz-analyzer/) and*.bak/*.bak-*(editor / manual backup files).
Fixed
- PZ build 42.x server logs now parse with proper level / prefix attribution. Previously, every B42 line failed
DebugServerPattern::LINEand the resulting ServerLog entries fell through as levelINFOwith no prefix. This silently disabledServerExceptionProblemandModMissingProblem(their regexes anchor on[timestamp]...at entry start, which a level-less orphan entry doesn't emit). The anchorlessEngineVersionInformationcontinued to fire against the joined entry text, producing the user-visible symptom "one Information badge, empty Problems panel" on B42 logs. The fix restores per-line parsing, re-enables both Problem classes, and makes the error-count badge populate correctly.
Test counts
- PHP suite: 287 tests, 654 assertions (up from 260 / 492 at v0.2.0).
- Python suite under
tools/pz-analyzer/: 32 tests (stdlibunittest, sub-10 ms).
0.2.0 — 2026-05-01
Render-time PII redaction utility added on the same calendar day as v0.1.0. Cut as a minor version bump rather than a patch because it adds a new public API surface (RedactorInterface plus the per-game implementation), which under semver is a minor change, not a patch. Consumers (notably iblogs) pin to ^0.2.0 to opt into the redactor-aware version.
Added
RedactorInterface(src/Util/RedactorInterface.php) andProjectZomboidRedactor(src/Util/ProjectZomboid/ProjectZomboidRedactor.php) — render-time PII filter that scrubs Steam IDs, player names, and world coordinates from Project Zomboid log content. Three independent toggles default to on. Designed as a string-in/string-out utility so consumers can apply it at any rendering or export step. Documented v1 limitations: in PvP combat lines, only the attacker's name and coords are redacted; victim's name and coords (afterhit) are deferred to v2. In admin lines,teleported X to <coords>coordinates are not redacted in v1.- 65 new test methods across six files under
test/tests/Util/Redactor/— per-category unit tests, combined / toggle / idempotence matrix, and integration coverage that drives all 11 existing PZ fixtures through the redactor end-to-end. Suite total: 260 tests, 492 assertions. docs/superpowers/specs/2026-04-30-redactor-design.mdflipped from "deferred" to "implemented" status. Plan committed atdocs/superpowers/plans/2026-05-01-redactor.md.
Changed
- New top-level
src/Util/directory introduced. The Redactor is its first occupant; future utilities (e.g. tokenising redactor variants) land here.
0.1.0 — 2026-05-01
First public release. Codex is a generic PHP log parsing and analysis framework with full Project Zomboid server-log support across eight analysers. The Composer package name is indifferentketchup/codex (the repository directory and Gitea slug are ik-codex; the package name is not).
Added
- Framework foundation — generic
Log/Entry/Line/Parser/Analyser/Detective/Insightpipeline forked from upstreamaternos/codexand renamed end-to-end toIndifferentKetchup\Codex\*in66a2fcc. ZeroAternos\Codex\*namespace references remain insrc/ortest/. FilenameDetectoratIndifferentKetchup\Codex\Detective\FilenameDetector— path-based detector that uses the newLogFileInterface::getPath()accessor to dispatch on a filename hint. Falls back tofalsefor path-less log files (StringLogFile,StreamLogFile).- Project Zomboid log subclasses (11) under
IndifferentKetchup\Codex\Log\ProjectZomboid\*covering every PZ server-log file type: a multi-lineProjectZomboidServerLogforDebugLog-server.txt, an abstractProjectZomboidEventLogbase for the ten single-line logs, and concrete subclasses foradmin.txt,BurdJournals.txt,chat.txt,ClientActionLog.txt,cmd.txt,item.txt,map.txt,PerkLog.txt,pvp.txt,user.txt. - Pattern classes (11) under
IndifferentKetchup\Codex\Pattern\ProjectZomboid\*holding regex string constants. Each<Type>Patterncarries aLINEregex used byPatternParser, plus named-group extractor regexes (FIELDS,COMBAT,MOD_LOAD, etc.) used by analysers. ProjectZomboidDetectiveatIndifferentKetchup\Codex\Detective\ProjectZomboid\ProjectZomboidDetective— pre-registers all 11 log subclasses in its constructor with paired filename-hint plus content-signature detectors.- Phase B.1 ServerLog analysers (3):
EngineVersionAnalyser(extracts engine version, build hash, and build date from the server banner),ModLoadAnalyser(mod load order plus missing-mod problems with attachedModMissingSolution),ServerExceptionAnalyser(Java exception type and stack-trace body, coalesced by exception type). - Phase B.2 PvP and Admin analysers (2):
PvpDamageAnalyser(filters zombie hits and zero-damage rows at the regex itself),AdminAuditAnalyser(verb-pattern dispatch across six admin actions: added item, added xp, granted access, changed option, reloaded options, teleported). - Phase B.3 deferred analysers (3) — first custom
Analysersubclasses in the tree, addressing logic that vanillaPatternAnalysercannot express:ConnectionFailureAnalyser(event pairing across the file),ItemDuplicationAnalyser(sliding-window heuristic withTHRESHOLD_COUNT=5,THRESHOLD_WINDOW_SECONDS=10),SkillProgressionAnomalyAnalyser(consecutive-snapshot delta withTHRESHOLD_DELTA=3). All three threshold constants ship with rationale docblocks and are tunable via subclass override. - Synthetic test fixtures under
test/src/Games/ProjectZomboid/fixtures/, hand-crafted from observed PZ log shapes with placeholder identifiers per the project's privacy rules: Steam IDs76561198000000001–76561198000000004, namesPlayer1/Player2/AdminUser/PlayerSuspect, generic coords. No real-log content reaches the index. - End-to-end tests validating each Log subclass's parser, each analyser's insight emission, and the Detective's dispatch behaviour against the synthetic fixtures. Final count: 195 tests, 412 assertions.
- Project documentation:
CLAUDE.mdwith framework architecture, pitfalls, and workflow conventions;README.mdwith worked Project Zomboid example and per-game support table; design specs and as-built plans for Phase B.1 / B.2 / B.3 plus a deferred-status spec for the codexRedactorutility, all underdocs/superpowers/.
Changed
- Layout: components-outer with game suffix. Every game's code lives at
IndifferentKetchup\Codex\<Component>\<Game>\*for the existing components (Analyser,Analysis,Detective,Log,Parser,Pattern). This is option 1 from the Phase A Step 2 layout decision; option 3 (a flatIndifferentKetchup\Codex\Games\<Game>\*tree) was originally proposed and was not selected. LICENSEretains the originalCopyright (c) 2019-2026 Aternos GmbHline per MIT requirements; the LICENSE file is byte-for-byte unchanged from the upstream import.composer.jsonrewritten inaae016d: package nameindifferentketchup/codex, MIT license, generic-framework description, single author entry, PSR-4 autoload roots set toIndifferentKetchup\Codex\and the test-fixture / test-suite namespaces, PHP>=8.4require constraint, PHPUnit^12dev dependency.tests.yamluses the modern$GITHUB_OUTPUTworkflow command instead of the deprecated::set-output(commit60f12bc). CI matrix runs PHP 8.4 and 8.5..gitignoreexcludesLogs.zip(real production log fixtures) and.scratch/(extracted reference logs), plus.claude/and.claude.local.mdfor personal Claude Code artefacts.
Deferred
- Other game implementations —
Minecraft,Hytale, andSevenDaysToDieare detective-stub-only. Each has a TODO<Game>Detectiveextending baseDetective; their per-component subdirectories underAnalyser,Log,Parser, andPatterncontain only.gitkeepplaceholders. Real implementations land if and when fixtures and demand exist. - Packagist publication — v0.1.0 is consumable via Composer's
vcsrepository entry pointing at the Gitea remote. Pushing to Packagist is a separate decision and is not in scope for this release.