Pet epics
| Document version | Date | Summary |
|---|---|---|
| v7 | 2026-07-24 | Archive the completed v0.2.0 epics and open the next release map |
| v8 | 2026-07-25 | Define the v0.3.0 embedded firmware foundation and project UX epics |
| v9 | 2026-07-25 | Add v0.3.0 release verification and hardening as the final epic |
| v10 | 2026-07-27 | Complete E17 after accepting the v0.3.0 architecture and release scope |
| v11 | 2026-07-27 | Record completion of E18, E19, and E20 |
| v12 | 2026-07-27 | Clarify the T-Display family and selected S3 variant contract |
| v13 | 2026-07-28 | Record completion of E21 |
| v14 | 2026-07-28 | Record completion of E22 |
| v15 | 2026-08-01 | Archive the completed v0.3.0 epics and open the next release map |
| v16 | 2026-08-02 | Define the v0.4.0 local persistence foundation epics |
| v17 | 2026-08-03 | Bring the wall-clock stamp and bounded absence into v0.4.0 scope |
| v18 | 2026-08-04 | Archive the completed v0.4.0 epics and await the next release map |
| v19 | 2026-08-05 | Define the v0.5.0 board runtime and embedded asset pipeline epics |
Status: Draft
Current release: v0.5.0
Related documents: Product specification, milestones, general architecture, and the release archives for v0.1.0, v0.2.0, v0.3.0, and v0.4.0.
1. Purpose
This document defines the product and engineering outcomes required by each epic.
An epic belongs to one release and contains multiple PBIs. An epic describes a verifiable outcome rather than a source directory, implementation phase, or team activity.
Epic identifiers are permanent and are not reused. Future releases continue the sequence instead of restarting at E01.
2. Epic completion rules
An epic is completed only when:
- all child PBIs are completed
- all epic completion criteria are satisfied
- required tests pass
- accepted architecture decisions are reflected in code and documentation
- new limitations are recorded in
known-limitations.md - deferred defects are recorded in
bugs.md - architecture deviations are documented
- verified support claims are not broader than the available evidence
An epic must not be marked completed because its main implementation exists while tests or required documentation remain unfinished.
3. Archived releases
Completed v0.1.0 epics are archived in release v0.1.0. That archive
holds E01 through E07 with their full outcomes, scope, and completion criteria.
Completed v0.2.0 epics are archived in release v0.2.0. That archive
holds E08 through E16 with their full outcomes, scope, and completion criteria.
Completed v0.3.0 epics are archived in release v0.3.0. That archive
holds E17 through E23 with their full outcomes, scope, and completion criteria.
Completed v0.4.0 epics are archived in release v0.4.0. That archive
holds E24 through E29 with their full outcomes, scope, and completion criteria.
Epic identifiers continue from E30. They are permanent and are not reused, so a future release
never restarts the sequence.
4. Release v0.5.0 epic map
| Epic | Title | Status | Primary outcome |
|---|---|---|---|
E30 | v0.5.0 architecture and release scope | Completed | The board runtime, the frontend split, the pack format direction, the verification composition, and the device evidence model for v0.5.0 are documented and accepted |
E31 | Board execution and panel bring-up | Completed | The classic T-Display can be flashed and monitored through a documented project command, and its panel is lit and measured on real hardware |
E32 | Continuous embedded runtime | Completed | The firmware application runs as a non-returning loop driven by a monotonic clock and a bounded delta, and survives a long device run |
E33 | TFT presentation frontend | Completed | A hosted-buildable TFT frontend composes the pet into one frame buffer and presents it through a thin ESP-IDF backend |
E34 | Embedded asset pack and converter | Completed | A deterministic build-time converter compiles the canonical manifest and images into one embedded asset pack with a decided format |
E35 | Embedded asset-backed presentation | Completed | The firmware image carries the pack, the reader resolves frames in place, and the canonical pet reaches the panel |
E36 | Board input and semantic actions | Planned | Both board buttons are sampled and filtered through a pure rule, and a filtered edge becomes an existing semantic action |
E37 | Release verification and hardening | Planned | The release meets its hosted, cross-build, device, limitation, and support-claim evidence requirements |
The release goal and expected capabilities are recorded in
milestones. The concrete architecture is recorded in
architecture for v0.5.0. PBIs for this release start at PBI-103 and the ADRs
its epics write continue from ADR-016, because ADR-015 was written during planning.
4.1 Dependency view
flowchart TD E30[E30 Architecture and scope] E31[E31 Board execution and panel bring-up] E32[E32 Continuous embedded runtime] E33[E33 TFT presentation frontend] E34[E34 Embedded asset pack and converter] E35[E35 Embedded asset-backed presentation] E36[E36 Board input and semantic actions] E37[E37 Release verification] E30 --> E31 E31 --> E32 E31 --> E33 E31 --> E34 E31 --> E36 E33 --> E35 E34 --> E35 E32 --> E37 E33 --> E37 E35 --> E37 E36 --> E37
Every epic descends from E30 through E31, because no epic may implement a design the release has
not accepted. The edges below E30 are ordering constraints rather than preferences.
E31 precedes everything that touches the device, because an epic that cannot flash a board and read
its output cannot produce evidence for anything it builds. It also precedes E34, which is the panel
before pipeline rule the roadmap recorded. The pack encoding is chosen against a measured colour
path, so a converter written first would be encoding for a display nobody had lit.
E33 and E34 both precede E35, because asset-backed presentation is the first place where a
composed frame and a generated artefact meet. Neither alone can produce it, and both can be finished
without it.
E36 depends on E31 alone. Its outcome is that a filtered edge becomes a semantic action that the
serial diagnostics report, which needs a running board rather than a presented pet. The visible
response to a button press is release-level integration evidence and belongs to E37, which keeps
E36 verifiable on its own.
E37 is the release-level convergence point. Testing is not deferred to it. Every implementation
epic carries its own tests and evidence, and E37 adds the end-to-end device observation, the final
gates, the support-claim review, the limitation status review, and documentation hardening.
5. E30: v0.5.0 architecture and release scope [+]
Release: v0.5.0
Status: Completed
Dependencies: None
5.1 Outcome
The release architecture defines the firmware run loop and time policy, the split between the common
TFT sources and the ESP-IDF backends, the ownership split between the pack and the board profile, the
hosted verification composition, the serial diagnostic contract, and the device evidence model for
v0.5.0.
The result is an accepted implementation plan that lets later epics build a decided design rather than negotiate one against a vendor SDK.
5.2 In scope
arch-v0.5.0.md- the continuous run loop, its time source, and its bounded delta policy
- the frontend split between hosted-buildable common sources and selectable ESP-IDF backends
- the ownership split between asset facts in the pack and board facts in the board profile
- the registered
firmware-tftcomposition and what claim it supports - the serial diagnostic line format and its event vocabulary
- the device evidence model, including what a maintainer observes and what a transcript proves
- the limitation intake for
LIM-012,LIM-013,LIM-015, and the newLIM-018
5.3 Out of scope
- implementing the loop, the frontend, the converter, the reader, or the input path
- measuring the panel
- fixing the final pixel encoding
- non-volatile storage, wireless facilities, and adapter work
5.4 Completion criteria
-
arch-v0.5.0.mdexists and follows the version architecture policy - the run loop, time source, and delta bound policy are recorded with their reasons
- the frontend split names which sources are hosted-buildable and which are backend-only
- the pack and the board profile have no overlapping ownership
- the
firmware-tftcomposition and its claim boundary are recorded - the serial diagnostic format and event vocabulary are recorded
- the support matrix separates hosted evidence, cross-build evidence, and device observation
- the decisions that need an ADR are named with the epic that will write each one
- open decisions are named for PBI or later-release resolution
5.5 Traceability
SPEC-NFR-001: portabilitySPEC-NFR-003: testabilitySPEC-NFR-006: maintainabilitySPEC-FR-029: frontend independenceLIM-012: the selected board has never been flashed or runLIM-013: no embedded asset storage or reader existsADR-016: the hosted firmware and TFT verification compositionarch-v0.5.0: sections 1, 2, 4, 5, 7, 8, 9, 10, and 11
6. E31: Board execution and panel bring-up [+]
Release: v0.5.0
Status: Completed
Dependencies: E30
6.1 Outcome
The classic LILYGO T-Display can be flashed and monitored through a documented project command, and its panel is lit, measured, and recorded as a board profile.
The result is the first physical evidence the project holds. Every later device claim depends on this epic being able to put an image on the board and read what it says.
6.2 In scope
./pet.py flashand./pet.py monitor, following the existing command-first grammar- the project command tests that cover the new surface
- the ESP-IDF display bring-up path over
esp_lcd, including the bus, the reset, and the backlight - a procedural diagnostic presentation sufficient to measure the panel, such as a colour and corner pattern
- measuring the visible area, the panel offsets, the native orientation, the transfer orientation, and the panel colour order
- recording the measured values in the classic board profile and marking which values remain vendor-documented
- the serial diagnostic line format and its first events
6.3 Out of scope
- presenting the pet
- the asset pack, the converter, and the reader
- the continuous run loop
- button sampling and semantic actions
- any board variant other than the classic one
6.4 Completion criteria
- the firmware can be flashed and monitored through the documented project command
- the command surface is covered by the project command test suite
- the panel is lit on the physical board and shows the diagnostic pattern
- the visible area, offsets, native orientation, transfer orientation, and colour order are measured and recorded
- the board profile distinguishes measured values from vendor-documented values
- the serial output follows the documented line format and event vocabulary
- the ESP-IDF build continues to configure, compile, and link
- the hosted compositions are unaffected and continue to pass the required gate
6.5 Traceability
SPEC-FR-026: varied frontend capabilitiesSPEC-NFR-005: responsivenessLIM-012: the selected board has never been flashed or runarch-v0.5.0: sections 5.4, 5.6, 7.3, and 8.7
7. E32: Continuous embedded runtime
Release: v0.5.0
Status: Completed
Dependencies: E31
7.1 Outcome
The firmware application runs as a non-returning loop driven by a monotonic platform clock and a bounded elapsed delta, and it survives a long continuous device run without resetting, stalling, or leaking.
The result is the difference between a board that boots and a companion that lives on a board.
7.2 In scope
- the run loop in
apps/firmware, which does not return in normal operation and does not busy spin - the monotonic time source behind a platform seam, and the conversion to milliseconds
- the bounded delta policy, including what is recorded when a delta is clamped
- a stepped lifecycle form so a host test can drive iterations with supplied time values
- the runtime and fault diagnostic events
- host tests over the stepped lifecycle
- a soak observation on the physical board, including the minimum free heap at both ends
- an ADR for the run loop and time source policy
7.3 Out of scope
- what is drawn during the loop
- asset resolution
- button input
- power management, sleep modes, and duty cycling
7.4 Completion criteria
- the application does not return in normal operation and does not busy spin
- the elapsed time delivered to the Core is monotonic and bounded
- a clamped delta is recorded through a diagnostic rather than silently dropped
- the stepped lifecycle is driven by host tests with supplied time values, including a clamp
- a two-hour device run shows no unexpected reset, no watchdog abort, no stalled presentation, and no continuously falling minimum free heap
- the run loop and time source policy are recorded in an ADR
- the firmware performs no dynamic allocation of its own
7.5 Traceability
SPEC-FR-013: explicit time progressionSPEC-FR-014: autonomous activitiesSPEC-FR-010: valid absenceSPEC-NFR-002: resource awarenessSPEC-NFR-005: responsivenessarch-v0.5.0: sections 5.2, 6.2, 8.1, and 8.8
8. E33: TFT presentation frontend
Release: v0.5.0
Status: Completed
Dependencies: E31
8.1 Outcome
A TFT frontend composes the pet into one frame buffer from a presentation snapshot and presents it through a thin ESP-IDF backend, with every composition decision asserted by host tests.
The result is the project’s second frontend and the first one whose platform half is small enough to be the only part a device has to confirm.
8.2 In scope
frontends/tftwith its public contract and its common sources- the registered
firmware-tftcomposition inconfig/compositions.jsonand the tooling it touches - one full frame buffer, composed whole and transferred whole
- skipping composition and transfer when the frame selection is unchanged
- role selection, integer scaling, placement, and clipping through the existing components
- the procedural fallback appearance drawn without any asset
- the ESP-IDF display backend, selected by a build option and absent from hosted builds
- host tests over composition, clipping, scaling, and the fallback
- an ADR for the frame buffer strategy
8.3 Out of scope
- the asset pack, the converter, and the reader
- button sampling and filtering
- partial or dirty-region updates
- any panel other than the classic one
8.4 Completion criteria
- the common sources build and their tests run in the
firmware-tftcomposition without ESP-IDF - no ESP-IDF header or symbol reaches a hosted composition
- the frontend receives a snapshot and never a mutable world pointer
- composition, scaling, placement, and clipping are asserted over a caller-owned buffer
- an unchanged frame selection composes nothing and transfers nothing
- the procedural fallback presents with no asset present
- the pet is visible on the physical panel through the fallback path
- the frame buffer strategy is recorded in an ADR
- the tooling that assumed no hosted firmware composition is reconciled rather than left to drift
8.5 Traceability
SPEC-FR-025: presentation stateSPEC-FR-026: varied frontend capabilitiesSPEC-FR-029: frontend independenceSPEC-NFR-002: resource awarenessSPEC-NFR-003: testabilityarch-v0.5.0: sections 5.3, 5.4, 5.10, 6.4, and 8.5
9. E34: Embedded asset pack and converter [+]
Release: v0.5.0
Status: Completed
Dependencies: E31
9.1 Outcome
A deterministic build-time converter compiles the canonical manifest and its images into one embedded asset pack whose format is decided, versioned, and recorded.
The result is the artefact that lets a runtime with no parser, no filesystem, and no PNG decoder present the same pet the desktop presents.
9.2 In scope
- the pack format, including its magic value, format version, compiled presentation structure, entry table, pixel encoding, and transparency representation
tools/assets/pack.py, using the standard library only- the converter’s manifest grammar reading as an isolated module with its own tests, so that the
collapse
ADR-015decides moves a module later rather than rewriting a program - the accepted PNG subset and the named rejection of everything outside it
- the pack generation build step and its output in the build directory
tools/tests/test_pack.pycovering determinism, known outputs, and rejections- an ADR for the pack format, its converter contract, and its compatibility promise
9.3 Out of scope
- reading the pack on a device
- embedding the pack into the firmware image
- changing the canonical manifest, its grammar, or its images
- moving the desktop frontend onto the pack
- collapsing the grammar onto one reader, which
ADR-015accepts and defers to a later release
9.4 Completion criteria
- the pack format is recorded in an ADR before the converter is implemented
- the format carries the compiled presentation structure derived from the canonical manifest
- the format carries no board offset, no rotation, and no panel colour order
- the declared pixel encoding matches what the measured panel consumes
- the converter is deterministic, so equal inputs produce equal bytes
- the converter rejects an unsupported image with a named reason rather than guessing
- the converter fails loudly rather than writing a partial pack
- the pack is generated into the build directory and no pack is committed
- the converter suite runs as a gate step beside the existing tool suites
- the grammar reading is a separate module with its own tests rather than being woven into the pack encoder, and the duplication it creates is recorded as a limitation
9.5 Traceability
SPEC-FR-025: presentation stateSPEC-NFR-002: resource awarenessSPEC-NFR-007: compatibility awarenessADR-007: canonical visual assets and manifestADR-015: the canonical manifest grammar has one readerADR-019: embedded asset pack format version 1LIM-013: no embedded asset storage or reader existsarch-v0.5.0: sections 5.7, 8.3, and 8.4
10. E35: Embedded asset-backed presentation [+]
Release: v0.5.0
Status: Completed
Dependencies: E33, E34
10.1 Outcome
The firmware image carries the pack, the reader validates and resolves it in place, and the canonical pet reaches the physical panel.
The result closes the embedded asset gap that has been open since v0.3.0, and it is the criterion a
fallback-only run does not satisfy.
10.2 In scope
- the pack reader in
components/assets, selected by a build option - validation of the header, the entry table, and the declared offsets before any lookup
- materialising the compiled presentation structure into a caller-owned manifest
- resolving frames as pointers into read-only memory without copying pixels
- linking the pack into the firmware image as embedded read-only bytes
- the TFT frontend consuming pack frames instead of the fallback when a pack is accepted
- host tests over valid packs, malformed packs, and the equivalence between the parsed manifest and the materialised one
10.3 Out of scope
- generating the pack, which
E34owns - a separate asset partition or a flashing lifecycle for assets
- runtime asset replacement or updates
- desktop consumption of the pack
10.4 Completion criteria
- the reader validates the header, the entry table, and every declared offset before a lookup
- a truncated, corrupted, or unknown-version pack is rejected rather than interpreted
- a rejected pack selects the procedural fallback and never ends the application
- the materialised manifest resolves the same role, animation, frame, and duration as the parsed manifest over every canonical role
- no pixel is copied out of the pack to present it
- the firmware image carries the pack and reports its size and entry count through diagnostics
- a canonical frame is visibly presented on the physical classic T-Display
- the embedded boundary check holds over the new sources
10.5 Traceability
SPEC-FR-025: presentation stateSPEC-FR-012: capability aware behaviourSPEC-NFR-002: resource awarenessSPEC-NFR-004: robustnessLIM-013: no embedded asset storage or reader existsarch-v0.5.0: sections 5.5, 6.4, 6.5, 8.3, and 8.8
11. E36: Board input and semantic actions
Release: v0.5.0
Status: Planned
Dependencies: E31
11.1 Outcome
Both board buttons are sampled and filtered through a pure debounce rule, and a filtered edge becomes an existing semantic action that the serial diagnostics report.
The result is the first physical user input the project has ever accepted, and it is accepted without opening the adapter interface question.
11.2 In scope
- the GPIO backend that configures both pins, samples their levels, and supplies timestamps
- the pure debounce rule beside the frontend that consumes it
- the mapping from a filtered edge to an existing semantic action, in the firmware application
- the behaviour of
GPIO 0at reset and during a run, recorded in the board profile - the
inputdiagnostic event - host tests over stable, bouncing, and held level sequences, and over unmapped edges
11.3 Out of scope
- inventing a new Core action for the second button
- adapters, sensors, and external sources
- gesture, long-press, or chord vocabularies beyond what the mapped action needs
- the visible pet response, which is release-level integration evidence in
E37
11.4 Completion criteria
- both pins are configured and sampled on the physical board
- the debounce rule is pure and is asserted by host tests over supplied levels and timestamps
- one press produces exactly one edge rather than one edge per sample
- a filtered edge produces an existing semantic action through the Core public API
- an unmapped edge produces no action and no diagnostic noise
- no GPIO number, pin, or button index reaches the Core
- the strapping behaviour of
GPIO 0is recorded, and the mapped action sits on a pin that behaves reliably - the
inputdiagnostic reports the button and the action it produced
11.5 Traceability
SPEC-FR-008: semantic actionsSPEC-FR-009: limited input operationSPEC-FR-036: input validationSPEC-NFR-003: testabilityarch-v0.5.0: sections 5.3, 5.4, 6.3, and 8.6
12. E37: Release verification and hardening
Release: v0.5.0
Status: Planned
Dependencies: E32, E33, E35, E36
12.1 Outcome
The release meets its hosted, cross-build, and device evidence requirements, its limitations are reconciled, and no claim it records is broader than the evidence behind it.
The result is a release that a reviewer who did not plan it can check.
12.2 In scope
- the audit gate from a clean tree over headless, desktop-sdl, and firmware-tft
- the ESP-IDF build evidence, including the image size and the embedded pack
- the end-to-end device observation, where a button press produces a visible pet response drawn from the pack
- the serial transcript that accompanies the device observation
- the soak result and the heap readings
- closing
LIM-012for the classic variant onesp32only - closing
LIM-013through the canonical frame evidence - keeping
LIM-015open and correcting its tracking column - opening
LIM-018for the absent hardware-in-the-loop gate - the support matrix, the release evidence file, and the release archive
- documentation hardening across the release documents
12.3 Out of scope
- new capabilities
- new board variants or targets
- deferred defect fixes that belong to a later release rather than this one
12.4 Completion criteria
-
./gate.py audit --all-compositionspasses from a clean tree over all three compositions - the ESP-IDF build is recorded with its framework version, toolchain, image size, and pack size
- a maintainer records a button press producing a visible pet response drawn from the pack
- the serial transcript follows the documented format and accompanies the observation
- the two-hour soak result and its heap readings are recorded
-
LIM-012is closed for the classic variant onesp32only, with no wider claim -
LIM-013is closed by the canonical frame evidence, and a fallback-only run would not have closed it -
LIM-015remains open and no longer names this release in its tracking column -
LIM-018is recorded with hosted assertions and physical observation kept apart - the support matrix records no device claim as automated evidence
- every
v0.5.0exit criterion in milestones is satisfied or explicitly carried with a reason
12.5 Traceability
SPEC-NFR-004: robustnessSPEC-NFR-006: maintainabilitySPEC-NFR-007: compatibility awarenessLIM-011: rendering and interaction remain manual evidenceLIM-012,LIM-013,LIM-015,LIM-018arch-v0.5.0: sections 7.2, 10.3, 10.4, and 10.5
13. Crosscutting rules
The following rules apply to every epic:
- code and developer documentation use British English
- Core code uses ISO C99
- public domain identifiers use the
petprefix - no hidden global mutable world is introduced
- time and randomness remain explicit
- tests are implemented with the behaviour they verify
- invalid public input must not partially mutate authoritative state
- no frontend, adapter, storage, or networking dependency enters the Core
- implementation remains within the assigned epic and PBI scope
- deferred work is recorded instead of being hidden in comments
14. PBI preparation rules
The next planning document is 03-pbis.md.
PBIs derived from these epics must:
- belong to exactly one epic
- produce one reviewable outcome
- include explicit in scope and out of scope boundaries
- include testable acceptance criteria
- identify dependencies
- link to relevant architecture sections
- identify required verification commands or evidence
- avoid combining implementation, unrelated refactoring, and future feature work
A PBI set should cover its epic completely before later epic implementation PBIs are marked ready.
15. References
- Pet product specification
- Pet milestones
- General Pet architecture
- Pet architecture for v0.1.0
- Pet architecture for v0.2.0
- Pet architecture for v0.3.0
- Pet architecture for v0.4.0
- Release v0.1.0 archive
- Release v0.2.0 archive
- Release v0.3.0 archive
- Release v0.4.0 archive
- Release planning process
- Release process
- Semantic Versioning 2.0.0
- arc42 architecture documentation