5.5 KiB
Task 7 — Angular typed API and signal-driven WorldStore report
Scope delivered
- Added typed public response models and
GameApiServicemethods for character, current location, travel start, and current travel. - Configured Angular's application providers with
HttpClient. - Added
WorldStorewith private writable and public read-only signals for character, world location, selection, travel, countdown, loading, and errors. - The store derives presentation-only countdown seconds from server
arrivesAt. At zero it polls the API and never assigns the target location locally. - Character and location are reloaded only after the API returns
COMPLETED.
Required preflight
- Re-read every document under
docs/, including the approved design and implementation plan, and inspected all three PNG reference images. - Read the user-supplied visual asset guide. The untracked
apps/web/public/images/directory anddocs/references/Ashen_Realms_Visual_Asset_Style_Guide_V1.mdremain unchanged and unstaged.
TDD evidence
RED
npm test --workspace=@ashen-realms/web -- --watch=false
Initial result: failed as expected because game-api.service,
game-api.models, and world.store did not exist. The compiler reported only
their unresolved imports from the newly added tests.
GREEN
npm test --workspace=@ashen-realms/web -- --watch=false --include='src/app/core/api/game-api.service.spec.ts' --include='src/app/features/world/world.store.spec.ts'
Result: 2 test files passed, 7 tests passed.
The store tests cover initial loading, target-only travel start, arrivesAt
countdown calculation, polling at zero without local arrival, and reload only
after COMPLETED.
Verification evidence
npm test --workspace=@ashen-realms/web -- --watch=false
# 3 test files passed, 9 tests passed
npm run build:web
# Angular production build completed successfully
npm exec --workspace=@ashen-realms/web -- prettier --check <Task-7 files>
# All matched files use Prettier code style
git diff --check -- <Task-7 files>
# exit 0
Review fix round 2
The transient-poll regression now asserts both phases: the failed poll exposes
Temporary failure, and the successful authoritative IDLE retry clears it.
The new assertion was RED against the prior implementation because the error
remained set after the retry. refreshCurrentTravel() now clears the polling
error only after a successful API response and before applying that response;
the countdown contract and all other error paths are unchanged.
Fresh verification:
npm test --workspace=@ashen-realms/web -- --watch=false --include='src/app/features/world/world.store.spec.ts'
# 1 test file passed, 9 tests passed
npm test --workspace=@ashen-realms/web -- --watch=false
# 3 test files passed, 13 tests passed
npm run build:web
# Angular production build completed successfully
npm exec --workspace=@ashen-realms/web -- prettier --check <Task-7 files>
# All matched files use Prettier code style
git diff --check -- <Task-7 files>
# exit 0
The web workspace declares neither a lint script nor an ESLint dependency, so
there is no repository-configured lint command to run for this task.
Deliberate limits and concerns
- The store retains a
COMPLETEDtravel response after its authoritative character/location refresh. The following API poll returnsIDLE; the later world UI can decide when to clear the completion presentation. - The mandated code-review workflow normally requires a reviewer subagent, but this task explicitly prohibited subagents. The implementation was instead reviewed directly against the task brief and verified through the focused and complete web test/build checks above.
Review fix round 1
Findings addressed
- A journey whose
arrivesAtwas already in the past made an immediate poll but also installed a countdown interval. This could overlap an outstanding request. - A late response after store destruction could still apply state and start follow-on work.
The store now makes a single immediate poll at local zero with no countdown
interval. It uses one in-flight poll at a time and schedules a deliberate
one-second retry when the server still returns TRAVELLING or a poll fails.
All late async continuations check the destroy flag before changing state or
scheduling timers. The browser still never declares arrival or changes the
location itself.
TDD evidence
npm test --workspace=@ashen-realms/web -- --watch=false --include='src/app/features/world/world.store.spec.ts'
RED result: 2 of 9 tests failed against the previous implementation. The
already-expired test observed three calls where a pending request must allow
only two, and the destroy test observed an unwanted second character/location
reload after a late COMPLETED response.
GREEN result: 1 test file passed, 9 tests passed. The expanded cases establish
that IDLE and continuing TRAVELLING do not reload authoritative character
or location data, expired/skewed client time remains single-flight/throttled,
a transient poll error retries and recovers, and destruction ignores a late
response.
Fresh verification
npm test --workspace=@ashen-realms/web -- --watch=false
# 3 test files passed, 13 tests passed
npm run build:web
# Angular production build completed successfully
npm exec --workspace=@ashen-realms/web -- prettier --check <Task-7 files>
# All matched files use Prettier code style
git diff --check -- <Task-7 files>
# exit 0