Captures the decision to forgo custom Analyser subclasses (the framework's
PatternAnalyser already handles multi-line entry text via Entry::__toString),
the five Insight components under src/Analysis/ProjectZomboid/, the new
DebugServerPattern::EXCEPTION constant for header+stack-body capture, the
PatternAnalyser configuration that ServerLog::getDefaultAnalyser will return,
the per-class coalescing semantics, and the test plan that drives the existing
synthetic debug-server-minimal.txt fixture end-to-end.
Captures the framework architecture, the docker-based PHP/Composer
runtime, the components-outer game subtree convention, the
PatternParser-and-named-groups gotcha, the workflow conventions that
emerged during the rename and ProjectZomboid build-out, and the
synthetic-only fixture rule for committed test data. Adds .claude/ and
.claude.local.md to .gitignore so Claude session state and personal
overrides don't ride along.
Constructor pre-registers every concrete ProjectZomboid Log subclass so
that detect() can dispatch on filename hint plus content signature.
Data-provider test verifies each of the eleven synthetic fixtures
resolves to its expected Log class via the public Detective surface.
Per-line warnings emitted by the BurdJournals mod, format
'[time] [BurdJournals] LEVEL: message.'. Parser captures time, the
[BurdJournals] tag as the entry prefix, and the LEVEL token. Detectors:
filename match plus content signature on the literal '[BurdJournals]'
tag bracket.
Two row variants: low-level Connection events and player join/disconnect
events. The LINE regex accepts both shapes; analysers route via
CONNECTION (action/index/guid/id) and PLAYER_EVENT (steamid/player/event)
named-group regexes. Detectors: filename match plus content signatures
on either variant.
Free-form English message body with verb-dispatched analyser regexes
(ADDED_ITEM, ADDED_XP, GRANTED_ACCESS, CHANGED_OPTION,
RELOADED_OPTIONS, TELEPORTED). Parser captures only the timestamp,
since the admin name itself can include parentheses or whitespace.
Detectors: filename match plus content signatures on
'added item Base.X in Y's inventory' and 'granted ROLE access level on'.
Two row variants share the file: Safe House toggles ([LOG] Safety:)
and Combat events ([INFO] Combat: ... weapon=... damage=...). Parser
captures time, level, and the subsystem token (Safety|Combat) as the
entry prefix. COMBAT and SAFETY regexes extract structured fields,
including support for negative Z coordinates from basement levels.
Synthetic fixture covers both variants and represents zombie/vehicle/
real-PvP weapon types so analysers can later filter on damage>0 and
weapon!=zombie.
Per-line skill snapshot log; each Login event is paired with a perks
row containing comma-separated Skill=N tokens. PERK_PAIR regex extracts
each pair via preg_match_all for analyser use. Detectors: filename
match plus content signature on the unique '[Cooking=N, Fitness=N,
Strength=N,' prefix of the perks-row bracket.
Per-line world object placement/removal log. LINE pattern handles both
integer and floating-point coordinates and both 'Base.X' and
'IsoObject (X)' object encodings. Detectors: filename match plus content
signature on the added/removed verbs paired with Base./IsoObject prefix.
Per-line item gain/loss event log. Parser captures only the timestamp;
analysers decompose location/delta/item via ItemPattern::FIELDS.
Detectors: filename match plus content signature on the
container/floor/inventory location verbs paired with a signed delta.
Per-line client RPC trace. Parser captures only the timestamp;
analysers decompose steamid/player/command/coords via CmdPattern::FIELDS.
Detectors: filename match plus content signature on the
'steamid "name" command @ x,y,z' line shape.
Strict 5-field bracketed format. Parser captures only the timestamp;
analysers that want steamid/action/player/coords/param decompose the
Line text via ClientActionPattern::FIELDS. Detectors: filename match
plus content signature on the IS{Enter,Exit}Vehicle / ISWalkToTimedAction
action tokens.
Handles both chat-engine events (bracketed level prefix) and bare
server-alert lines via an optional level group. Detectors: filename
match on _chat.txt plus content signatures for ChatMessage{...} log
entries and the chat-server initialization banner. CHAT_MESSAGE and
SERVER_ALERT named-group regexes ride along on ChatPattern for analyser
extraction in phase B.
Concrete Log subclass for the engine debug log. Captures time, level,
and subsystem prefix per entry; stack-trace continuation lines attach
to the triggering ERROR entry via PatternParser's append-on-no-match
behaviour. Detectors: filename match on DebugLog-server.txt plus two
content signatures (the version=X.Y.Z+hash banner and the level/
subsystem/f/t/st header shape). Pattern constants live in
src/Pattern/ProjectZomboid/DebugServerPattern.php with named groups
ready for analyser use in phase B. Synthetic fixture under
test/src/Games/ProjectZomboid/fixtures/ uses zeroed identifiers and
placeholder paths.
ProjectZomboidLog (abstract): extends AnalysableLog, implements
DetectableLogInterface. Centralises the PZ timestamp format
('d-m-y H:i:s.v') and UTC default timezone, plus a makePatternParser()
helper so concrete subclasses only specify their line regex and capture
group names. ProjectZomboidEventLog (abstract): marker base for the ten
single-line structured PZ logs, distinct from the multi-line
ProjectZomboidServerLog. Concrete subclasses follow.
New Detector that matches a configured regex against
LogFileInterface::getPath(). Returns a settable weight on match (default
0.95) and false otherwise, including when the log file has no known path
(StringLogFile, StreamLogFile). Lets game-specific Detectives prefer the
filename hint over content signatures when an upload's original name is
preserved.
Add LogFileInterface::getPath(): ?string so detectors can dispatch on a
filename hint when the original path is known. Default implementation on
the abstract LogFile base returns null; PathLogFile records its
constructor argument. StringLogFile and StreamLogFile inherit the null
default. Tests cover both the path and null-fallback cases.
Add empty per-component subdirectories under src/{Analyser,Log,Parser,Pattern}/SevenDaysToDie/
with .gitkeep markers, plus SevenDaysToDieDetective stub extending the base Detective with
a TODO body. Smoke test under test/tests/Games/SevenDaysToDie/ asserts the detective is
instantiable. Directory name is alphabetic because PHP class names cannot begin with a digit.
Add empty per-component subdirectories under src/{Analyser,Log,Parser,Pattern}/Hytale/
with .gitkeep markers, plus HytaleDetective stub extending the base Detective with
a TODO body. Smoke test under test/tests/Games/Hytale/ asserts the detective is
instantiable.
Add empty per-component subdirectories under src/{Analyser,Log,Parser,Pattern}/ProjectZomboid/
with .gitkeep markers, plus ProjectZomboidDetective stub extending the base Detective with
a TODO body. Smoke test under test/tests/Games/ProjectZomboid/ asserts the detective is
instantiable.
Add empty per-component subdirectories under src/{Analyser,Log,Parser,Pattern}/Minecraft/
with .gitkeep markers, plus MinecraftDetective stub extending the base Detective with
a TODO body. Smoke test under test/tests/Games/Minecraft/ asserts the detective is
instantiable. Introduces src/Pattern/ as a new top-level component directory.
Bulk substitution across all PHP files in src/ and test/. Covers
namespace declarations, use statements, fully-qualified class
references, and @package PHPDoc tags. No logic changes.