phase: 01_fix_history_xss
Build and Push Container / build-and-push (push) Successful in 26s

**Phase 01 — final verification pass (all criteria green)**

- Verified M-1 fix in `src/terminal.js`: ArrowUp / ArrowDown(`>0`) / ArrowDown-else now route through `updateDisplay()` (`textContent`); no `innerHTML` sink touches `cmdLine`/`commandHistory`.
- `grep -n innerHTML src/terminal.js` → 12 hits, all allowed (static prompt literals, `clear`/prank wipes, `outLine.innerHTML = output` gated on the static canned `neofetch` string). **C1 ✓**
- XSS regression test at `tests/e2e/02-terminal.spec.js:156` present + passing; re-proved it is a real guard: re-injected the old `innerHTML` recall into `dist/terminal.*.js` → test failed (`#xss-marker` received 1); rebuild → byte-identical to `src/`. **C2 ✓**
- `./build.sh` → `dist/` OK; `npm test` → **45 passed (0 failed)**; `bash .agents/validate.sh` → **exit 0** (suite + repo-hygiene gates). **C3 ✓**
- Branch coverage of modified code: all 3 recall arms asserted (ArrowUp ×2 specs, ArrowDown `>0` in the existing history spec, ArrowDown-else → empty prompt in the new spec) → >90% gate met; no JS coverage/lint toolchain exists in the locked stack, so lint = `node --check src/*.js tests/e2e/*.js playwright.config.js` + `bash -n build.sh .agents/validate.sh` — clean.
- C4 ✓ terminal/vim/achievements/menu specs all green; only the three recall branches changed.
- Docs (step 6, full README/AGENTS review): README — run section now states the image already contains the built `dist/` (mount `dist/`, never `src/`); new “Serving & configuration” section for `nginx.conf`, incl. **empirically measured** (built image on 127.0.0.1:8124) that `/`, `/index.html` and hashed assets currently return *only* cache headers — the `add_header` non-merge gap = finding M-4/Phase 03; TLS/HSTS-at-edge rule; Quadlet section fixed (unit is not in this repo; Quadlet generates `homepage.service`, so `… start homepage.service`, and `systemctl enable` is a no-op for transient Quadlet units → `[Install]` + `daemon-reload` + linger); Development gained the Node 20+ floor, `npx playwright install chromium`, and `.agents/validate.sh`. AGENTS.md — added the validate.sh gate, flagged `./scripts/check-headers.sh` as not yet in the repo (Phase 03), and scoped the M-1 rule with the allowed-`innerHTML` list.
- Notable: `.agents/PLAN.md` still says “44 tests” (3 places) and its §7 roadmap omits phases 04/05 — left untouched per the no-PLAN-edit rule; flag for the next PLAN review. No live-infra touched (temp podman image built/removed for the header measurement only).
- Next pending phase: `02_simulate_fetch_commands`.
This commit is contained in:
2026-10-22 22:45:40 -04:00
parent a2f331e526
commit dcd066d953
30 changed files with 2343 additions and 27 deletions
@@ -0,0 +1,50 @@
# Phase 04 — Add Huntington National Bank role to work experience
**Story:** n/a
**Context:** `src/index.html` `#experience` timeline, `.agents/PLAN.md` §2 (static-first — content-only change, no new technology)
## Objective
Update the work-experience timeline with the user's current role: **Lead MLOps
Engineer at Huntington National Bank (Jun 2026 – Present)**, inserted as the
new first (most recent) timeline entry with three bullet points covering the
agentic vulnerability-remediation toolkit, LLM harness skills for business
automation, and the 6-person offshore team building the developer landing
zone. The previous Nimbis "DevOps Manager" entry is updated from
`Jan 2022 – Present` to `Jan 2022 – Apr 2026`. Lock the change with a
Playwright regression test.
## Dependencies
— (none)
## Tasks
1. `01_add_timeline_entry.md` — Insert the new Huntington National Bank timeline entry at the top of the `#experience` timeline and update the Nimbis DevOps Manager end date.
2. `02_experience_regression_test.md` — Add a Playwright test proving the new entry is first, complete, and correctly dated, and that the Nimbis entry no longer claims "Present".
## Testing & Quality
- Unit/integration: no JS logic changes in this phase — `src/index.html`
content only. The quality gate is the E2E regression test (task 2) plus the
full suite.
- Coverage: **>90%** on new/modified code — vacuously satisfied (no
JS/CSS/TS code is modified); the E2E suite is the binding gate.
- E2E: full Playwright suite (`npm test`) green.
- The phase is "Complete" only when the **entire** project test suite passes
100% (every test in the project, not just this phase's — pre-existing
failures included) and achieves **>90% code coverage** on new/modified code.
## Documentation & Consistency
- The final pass reviews `README.md` and `AGENTS.md` in full against the
project as it stands after this phase — fixing every inconsistency found,
**including pre-existing ones not caused by this phase**.
- Tasks update `README.md`/`AGENTS.md` immediately when their own changes are
user-visible (setup, commands, configuration, features, conventions).
## Completion Criteria
- [ ] `grep -c "Huntington National Bank" dist/index.html` returns 1 and
`grep -n "Jun 2026" dist/index.html` shows the `– Present` date span
- [ ] Nimbis "DevOps Manager" date reads `Jan 2022 – Apr 2026` in
`dist/index.html` (no second `– Present` entry in `#experience`)
- [ ] new regression test present in `tests/e2e/01-page.spec.js` and passing
- [ ] `./build.sh && npm test` fully green (45+ tests)
- [ ] no behavior change in completed work (terminal, vim, achievements, menu)
- [ ] README.md and AGENTS.md are accurate and consistent with the whole
project (verified in the final pass)
@@ -0,0 +1,65 @@
# Task 01 — Add Huntington National Bank timeline entry
**Phase:** `04_huntington_role` · **Story:** n/a
## Objective
Insert the new top work-experience entry (Lead MLOps Engineer, Huntington
National Bank, Jun 2026 – Present) into the `#experience` timeline and close
out the Nimbis "DevOps Manager" date span.
## Work
1. `src/index.html` — inside `<section id="experience">`, insert the block
below **immediately before** the existing first
`<div class="timeline-item fade-in" role="listitem">` (the Nimbis
"DevOps Manager" entry), keeping the file's existing 16/20/24/28-space
indentation exactly:
```html
<div class="timeline-item fade-in" role="listitem">
<div class="timeline-marker"></div>
<div class="timeline-content">
<div class="timeline-header">
<h3>Lead MLOps Engineer</h3>
<span class="timeline-company">Huntington National Bank</span>
</div>
<span class="timeline-date">Jun 2026 – Present</span>
<ul class="timeline-list">
<li>Building an enterprise agentic vulnerability remediation
toolkit and workflow to resolve millions of vulnerabilities.</li>
<li>Creating and distributing LLM harness skills that automate
business problems — including ServiceNow incident response —
at machine speed.</li>
<li>Leading a team of 6 offshore engineers to build a developer
landing zone with agentic tools that build pipelines, plan
work, and make documentation searchable.</li>
</ul>
</div>
</div>
```
(Use the en dash `–` U+2013 in the date span, matching every other
`timeline-date` value; use the em dash `—` only in the middle bullet,
matching the copy above. Wrap long `<li>` lines at the same width as
neighboring entries, 4-space continuation indent.)
2. `src/index.html` — in the Nimbis "DevOps Manager" entry, change its
`<span class="timeline-date">Jan 2022 – Present</span>` to
`<span class="timeline-date">Jan 2022 – Apr 2026</span>`.
3. `./build.sh` — rebuild `dist/`.
## Testing & Quality
- Unit/integration: content-only change — no new JS logic; the E2E regression
test is task 2, and the full suite is the gate.
- Coverage: **>90%** on this task's new/modified code — vacuously satisfied
(HTML content only, no JS/CSS modified).
## Completion Criteria
- [ ] `grep -c "Huntington National Bank" src/index.html` returns 1
- [ ] `grep -n "Jun 2026 – Present" src/index.html` matches the new entry
- [ ] `grep -n "Jan 2022 – Apr 2026" src/index.html` matches the Nimbis
"DevOps Manager" entry; `grep -c "– Present" src/index.html` returns 1
- [ ] `./build.sh` succeeds and the same three greps pass on
`dist/index.html`
- [ ] `npm test` fully green (44 tests — the new test lands in task 2)
- [ ] README.md/AGENTS.md updated for anything user-visible this task changes
(the phase's final pass re-checks both project-wide)
- [ ] no behavior change in completed work
@@ -0,0 +1,55 @@
# Task 02 — Experience timeline regression test
**Phase:** `04_huntington_role` · **Story:** n/a
## Objective
Lock the work-experience change with a Playwright regression test: the
Huntington National Bank entry is the first, most-recent timeline item with
its three bullets and `Jun 2026 – Present` date, and the Nimbis
"DevOps Manager" entry now ends `Apr 2026` instead of `Present`.
## Work
1. `tests/e2e/01-page.spec.js` — inside the existing
`test.describe('Page structure', ...)` block (after the
"all major sections exist and are in the DOM" test), add one test,
matching the file's existing style:
```js
test('experience timeline leads with Huntington National Bank role', async ({ page }) => {
const items = page.locator('#experience .timeline-item');
await expect(items).toHaveCount(5);
const first = items.first().locator('.timeline-content');
await expect(first.locator('h3')).toHaveText('Lead MLOps Engineer');
await expect(first.locator('.timeline-company')).toHaveText('Huntington National Bank');
await expect(first.locator('.timeline-date')).toHaveText('Jun 2026 – Present');
const bullets = first.locator('.timeline-list li');
await expect(bullets).toHaveCount(3);
await expect(bullets.nth(0)).toContainText('agentic vulnerability remediation');
await expect(bullets.nth(1)).toContainText('LLM harness skills');
await expect(bullets.nth(1)).toContainText('ServiceNow');
await expect(bullets.nth(2)).toContainText('developer landing zone');
// previous role's end date was closed out
const nimbisManager = items.nth(1).locator('.timeline-content');
await expect(nimbisManager.locator('h3')).toHaveText('DevOps Manager');
await expect(nimbisManager.locator('.timeline-date')).toHaveText('Jan 2022 – Apr 2026');
});
```
(Use the en dash `–` U+2013 in the expected date strings to match the
markup.)
2. `./build.sh && npm test` — rebuild and run the full suite.
## Testing & Quality
- Unit/integration: the new test covers (a) entry order (HNB first, Nimbis
DevOps Manager second, 5 entries total), (b) title/company/date of the new
entry, (c) all three bullets' key phrases, and (d) the Nimbis entry's
closed-out end date.
- Coverage: **>90%** on this task's new/modified code — test-only change;
the E2E suite is the binding gate.
## Completion Criteria
- [ ] the new test is present in `tests/e2e/01-page.spec.js` and passes
- [ ] `./build.sh && npm test` fully green (45 tests)
- [ ] README.md/AGENTS.md updated for anything user-visible this task changes
(the phase's final pass re-checks both project-wide)
- [ ] no behavior change in completed work
@@ -0,0 +1,62 @@
# Phase 05 — Update Featured Projects (Brain of Reese, ServWaf, Local AI Stack)
**Story:** n/a
**Context:** `src/index.html` `#projects` section (6 `project-card`s), `~/Projects/Personal/brain_of_reese/README.md`, `~/Projects/StackExpected/ServWall/README.md`, `~/Projects/Experimental/gufo/README.md`
## Objective
Refresh the Featured Projects grid: (a) replace the "Self-Hosted Services"
card with a **Brain of Reese** card (RAG chatbot over homelab docs;
pgvector ∪ Postgres full-text hybrid search with RRF fusion; self-hosted
LLM; source `https://gitea.reeseapps.com/Experimental/brain-of-reese` —
verified live) and move it to the **first** slot; (b) replace the
"Kubernetes Cluster" card with a **ServWaf** card (Go network WAF —
declarative YAML rules, rate limiting, attack-pattern inspection, opt-in
local-AI verdict, TLS/HTTP3 edge — **closed source: no source link**,
user decision) in its place; (c) update the **Local AI Stack** card to
replace Ollama with **vLLM, Gufo, and llama.cpp** (copy, tech tags, and
code preview). Lock with a Playwright regression test.
## Dependencies
— (none)
## Tasks
1. `01_brain_of_reese_card.md` — Delete the Self-Hosted Services card; insert the Brain of Reese card as the first card in `#projects`.
2. `02_servwaf_card.md` — Replace the Kubernetes Cluster card with the ServWaf card (description only, no source link).
3. `03_update_local_ai_stack.md` — Update the Local AI Stack card: replace Ollama with vLLM/Gufo/llama.cpp in the copy, tech tags, and code preview.
4. `04_projects_regression_test.md` — Add a Playwright test locking card count, order, the updated Local AI Stack tags, and the absence of the two removed card titles.
## Testing & Quality
- Unit/integration: no JS logic changes in this phase — `src/index.html`
content only. The quality gate is the E2E regression test (task 4) plus
the full suite.
- Coverage: **>90%** on new/modified code — vacuously satisfied (no
JS/CSS/TS code is modified); the E2E suite is the binding gate.
- E2E: full Playwright suite (`npm test`) green.
- The phase is "Complete" only when the **entire** project test suite passes
100% (every test in the project, not just this phase's — pre-existing
failures included) and achieves **>90% code coverage** on new/modified code.
## Documentation & Consistency
- The final pass reviews `README.md` and `AGENTS.md` in full against the
project as it stands after this phase — fixing every inconsistency found,
**including pre-existing ones not caused by this phase**.
- Tasks update `README.md`/`AGENTS.md` immediately when their own changes are
user-visible (setup, commands, configuration, features, conventions).
## Completion Criteria
- [ ] `grep -c "project-card fade-in" src/index.html` returns 6, and the
same holds in `dist/index.html`
- [ ] first `project-card` in `#projects` (in `dist/index.html`) is
"Brain of Reese" and its card links to
`https://gitea.reeseapps.com/Experimental/brain-of-reese`
- [ ] `grep -c "Self-Hosted Services\|Kubernetes Cluster" src/index.html`
returns 0 (project-card titles removed; the words may still appear in
the out-of-scope About/Skills sections — e.g. "Kubernetes" skill tag)
- [ ] the Local AI Stack card (in `dist/index.html`) contains vLLM, Gufo,
and llama.cpp and no "Ollama"
- [ ] new regression test present in `tests/e2e/01-page.spec.js` and passing
- [ ] `./build.sh && npm test` fully green (45+ tests)
- [ ] no change to the Skills section, About section, or any other section
outside `#projects`
- [ ] README.md and AGENTS.md are accurate and consistent with the whole
project (verified in the final pass)
@@ -0,0 +1,76 @@
# Task 01 — Brain of Reese card (first slot)
**Phase:** `05_update_projects_section` · **Story:** n/a
## Objective
Remove the "Self-Hosted Services" project card and insert the new
**Brain of Reese** card as the **first** card in `#projects` (immediately
before the "Reverse Proxy Infrastructure" card).
## Work
1. `src/index.html` — inside `<section id="projects">`, delete the entire
`project-card` block whose `<h3>` is "Self-Hosted Services" (the card
containing the `- Immich / - Jellyfin / …` code block).
2. `src/index.html` — insert the block below **immediately before** the
existing first `project-card` (the "Reverse Proxy Infrastructure"
card), matching the file's 16/20/24/28-space indentation. For the
`<div class="project-links">…</div>` (Gitea SVG) block, copy the
existing one from the "Reverse Proxy Infrastructure" card verbatim and
change only the `href` to
`https://gitea.reeseapps.com/Experimental/brain-of-reese`:
```html
<div class="project-card fade-in" role="listitem">
<div class="project-preview">
<div class="code-block">
<div class="code-line"><span class="code-comment"># Hybrid search: pgvector cosine ∪ Postgres full-text</span></div>
<div class="code-line"><span class="code-keyword">def</span> <span class="code-function">retrieve</span>(<span class="code-variable">query</span>, <span class="code-variable">k</span>=<span class="code-variable">5</span>):</div>
<div class="code-line">&nbsp;&nbsp;<span class="code-variable">vec</span> = <span class="code-function">pgvector</span>.<span class="code-function">cosine</span>(<span class="code-variable">query</span>)</div>
<div class="code-line">&nbsp;&nbsp;<span class="code-variable">fts</span> = <span class="code-function">postgres</span>.<span class="code-function">full_text</span>(<span class="code-variable">query</span>)</div>
<div class="code-line">&nbsp;&nbsp;<span class="code-variable">chunks</span> = <span class="code-function">rrf_fuse</span>(<span class="code-variable">vec</span>, <span class="code-variable">fts</span>, <span class="code-variable">k</span>)</div>
<div class="code-line">&nbsp;&nbsp;<span class="code-keyword">return</span> <span class="code-function">llm</span>.<span class="code-function">chat</span>(<span class="code-function">document</span>(<span class="code-variable">chunks</span>))</div>
<div class="code-line">&nbsp;</div>
</div>
</div>
<div class="project-info">
<h3>Brain of Reese</h3>
<p>A chippy, honest RAG chatbot over homelab documentation — git repositories, local
directories, and uploaded archives. Hybrid search (pgvector cosine ∪ Postgres
full-text search, Reciprocal Rank Fusion) feeds the whole relevant document to a
self-hosted LLM and streams back a grounded answer; when it has no notes it
admits it and suggests questions it can answer.</p>
<div class="project-meta">
<div class="project-tech">
<span>FastAPI</span>
<span>pgvector</span>
<span>Postgres</span>
<span>Playwright</span>
</div>
<div class="project-links">
<!-- copied from the Reverse Proxy Infrastructure card, href changed -->
</div>
</div>
</div>
</div>
```
3. `./build.sh` — rebuild `dist/`.
## Testing & Quality
- Unit/integration: content-only change — no new JS logic; the E2E
regression test is task 4, and the full suite is the gate.
- Coverage: **>90%** on this task's new/modified code — vacuously satisfied
(HTML content only, no JS/CSS modified).
## Completion Criteria
- [ ] `grep -c "project-card fade-in" src/index.html` returns 6
- [ ] `grep -n "Brain of Reese" src/index.html` matches once, and that card
is the first `project-card` inside `#projects`
- [ ] `grep -c "Self-Hosted Services" src/index.html` returns 0
- [ ] `grep -n "gitea.reeseapps.com/Experimental/brain-of-reese"
src/index.html` matches inside the new card
- [ ] `./build.sh` succeeds and the same greps pass on `dist/index.html`
- [ ] `npm test` fully green (44 tests — new test lands in task 4)
- [ ] README.md/AGENTS.md updated for anything user-visible this task changes
(the phase's final pass re-checks both project-wide)
- [ ] no behavior change in completed work
@@ -0,0 +1,69 @@
# Task 02 — ServWaf card (replaces Kubernetes Cluster)
**Phase:** `05_update_projects_section` · **Story:** n/a
## Objective
Replace the "Kubernetes Cluster" project card, in place (last slot), with
the **ServWaf** card. ServWaf is **closed source** (user decision): the
card carries **no** `project-links` block — description only.
## Work
1. `src/index.html` — inside `<section id="projects">`, replace the entire
`project-card` block whose `<h3>` is "Kubernetes Cluster" (the card
containing the `# Kubernetes with k3s` code block) with the block below,
matching the file's 16/20/24/28-space indentation. Note: this card has
**no** `<div class="project-links">` — the `project-meta` div contains
only `project-tech` (the flex layout handles a single child).
```html
<div class="project-card fade-in" role="listitem">
<div class="project-preview">
<div class="code-block">
<div class="code-line"><span class="code-comment"># ServWaf — declarative rules</span></div>
<div class="code-line"><span class="code-variable">ratelimit</span>:</div>
<div class="code-line">&nbsp;&nbsp;<span class="code-variable">per_ip</span>: <span class="code-string">20 rps, burst 40</span></div>
<div class="code-line"><span class="code-variable">rules</span>:</div>
<div class="code-line">&nbsp;&nbsp;- <span class="code-keyword">deny</span> <span class="code-variable">if</span> <span class="code-variable">user_agent</span> =~ <span class="code-string">"curl|wget"</span></div>
<div class="code-line">&nbsp;&nbsp;- <span class="code-keyword">flag</span> <span class="code-variable">if</span> <span class="code-variable">body</span> =~ <span class="code-string">"(?i)union\s+select"</span></div>
<div class="code-line"><span class="code-variable">ai</span>:</div>
<div class="code-line">&nbsp;&nbsp;<span class="code-variable">endpoint</span>: <span class="code-string">"http://aipi.reeseapps.com/v1"</span></div>
</div>
</div>
<div class="project-info">
<h3>ServWaf</h3>
<p>A network Web Application Firewall written in Go, sitting in line between clients
and the origin. Declarative YAML rules (user agent, IP/CIDR, URL and body
regexes), per-IP rate limiting, attack-pattern inspection (SQL injection, XSS,
path traversal, CRLF, scanner probes), opt-in self-hosted local-AI verdicts,
TLS termination, and an opt-in HTTP/3 (QUIC) edge.</p>
<div class="project-meta">
<div class="project-tech">
<span>Go</span>
<span>YAML</span>
<span>HTTP/3</span>
<span>Podman</span>
</div>
</div>
</div>
</div>
```
2. `./build.sh` — rebuild `dist/`.
## Testing & Quality
- Unit/integration: content-only change — no new JS logic; the E2E
regression test is task 4, and the full suite is the gate.
- Coverage: **>90%** on this task's new/modified code — vacuously satisfied
(HTML content only, no JS/CSS modified).
## Completion Criteria
- [ ] `grep -c "project-card fade-in" src/index.html` returns 6
- [ ] `grep -n "ServWaf" src/index.html` matches the new card's `<h3>`
- [ ] `grep -c "Kubernetes Cluster" src/index.html` returns 0
- [ ] the ServWaf card (last card in `#projects`) contains no
`project-links` div and no `gitea.reeseapps.com` href
- [ ] `./build.sh` succeeds and the same greps pass on `dist/index.html`
- [ ] `npm test` fully green (44 tests — new test lands in task 4)
- [ ] README.md/AGENTS.md updated for anything user-visible this task changes
(the phase's final pass re-checks both project-wide)
- [ ] no behavior change in completed work
@@ -0,0 +1,59 @@
# Task 03 — Update Local AI Stack card (vLLM, Gufo, llama.cpp)
**Phase:** `05_update_projects_section` · **Story:** n/a
## Objective
Update the "Local AI Stack" project card so Ollama is replaced by **vLLM,
Gufo, and llama.cpp** in the description, tech tags, and code preview.
Everything else on the card (LocalAI, LiteLLM, Bifrost, Langfuse, CUDA/
ROCm) stays.
## Work
1. `src/index.html` — in the "Local AI Stack" card, replace the `<p>` copy
with:
```html
<p>Complete local AI infrastructure: vLLM, Gufo, and llama.cpp for inference, LiteLLM as a
unified API proxy, Bifrost for model routing, and Langfuse for observability. Supports
both CUDA and ROCm.</p>
```
2. `src/index.html` — in that card's `project-tech` div, replace the
`<span>Ollama</span>` with three spans in this order:
`<span>vLLM</span> <span>Gufo</span> <span>llama.cpp</span>`
(final tag list: vLLM, Gufo, llama.cpp, LocalAI, LiteLLM, Langfuse).
3. `src/index.html` — in that card's `code-block`, replace the whole block
(the `from ollama import Client` … `# LiteLLM proxy for unified API`
lines) with:
```html
<div class="code-line"><span class="code-comment"># Inference engines</span></div>
<div class="code-line"><span class="code-variable">engines</span> = {</div>
<div class="code-line">&nbsp;&nbsp;<span class="code-string">"vllm"</span>: <span class="code-string">"cuda"</span>, <span class="code-comment"># high-throughput serving</span></div>
<div class="code-line">&nbsp;&nbsp;<span class="code-string">"gufo"</span>: <span class="code-string">"rocm"</span>, <span class="code-comment"># Strix Halo inference</span></div>
<div class="code-line">&nbsp;&nbsp;<span class="code-string">"llama.cpp"</span>: <span class="code-string">"gguf"</span>, <span class="code-comment"># CPU/GPU fallback</span></div>
<div class="code-line">}</div>
<div class="code-line">&nbsp;</div>
<div class="code-line"><span class="code-comment"># LiteLLM proxy for unified API</span></div>
```
4. `./build.sh` — rebuild `dist/`.
## Testing & Quality
- Unit/integration: content-only change — no new JS logic; the E2E
regression test is task 4, and the full suite is the gate.
- Coverage: **>90%** on this task's new/modified code — vacuously satisfied
(HTML content only, no JS/CSS modified).
## Completion Criteria
- [ ] within the Local AI Stack card in `src/index.html`: no "Ollama"
anywhere, and "vLLM", "Gufo", "llama.cpp" each present (copy, tags,
and preview)
- [ ] "LocalAI", "LiteLLM", "Langfuse" (and "Bifrost" in the copy) are
still present on the card
- [ ] `./build.sh` succeeds and the same checks pass on
`dist/index.html`
- [ ] `npm test` fully green (44 tests — new test lands in task 4)
- [ ] README.md/AGENTS.md updated for anything user-visible this task changes
(the phase's final pass re-checks both project-wide)
- [ ] no behavior change in completed work
@@ -0,0 +1,64 @@
# Task 04 — Projects grid regression test
**Phase:** `05_update_projects_section` · **Story:** n/a
## Objective
Lock the Featured Projects change with a Playwright regression test: six
cards in the new order (Brain of Reese first, ServWaf last), the Local AI
Stack card showing vLLM/Gufo/llama.cpp with no Ollama, and the removed
"Self-Hosted Services" / "Kubernetes Cluster" titles absent.
## Work
1. `tests/e2e/01-page.spec.js` — inside the existing
`test.describe('Page structure', ...)` block, add one test, matching the
file's existing style:
```js
test('featured projects show the six updated cards in order', async ({ page }) => {
const cards = page.locator('#projects .project-card');
await expect(cards).toHaveCount(6);
const titles = await cards.locator('.project-info h3').allTextContents();
expect(titles).toEqual([
'Brain of Reese',
'Reverse Proxy Infrastructure',
'Dynamic DNS Service',
'Local AI Stack',
'Deployment Automation',
'ServWaf',
]);
// Brain of Reese leads, with its source link
const brain = cards.first();
await expect(brain.locator('.project-tech span')).toHaveCount(4);
await expect(brain).toHaveText(/RAG chatbot/i);
await expect(brain.locator('a[href="https://gitea.reeseapps.com/Experimental/brain-of-reese"]')).toBeAttached();
// Local AI Stack: Ollama replaced by vLLM, Gufo, llama.cpp
const ai = cards.nth(3);
await expect(ai.locator('.project-tech')).toContainText(['vLLM', 'Gufo', 'llama.cpp']);
await expect(ai.locator('.project-tech')).toContainText(['LocalAI', 'LiteLLM', 'Langfuse']);
await expect(ai).not.toContainText('Ollama');
// ServWaf is closed source — description only, no source link
await expect(cards.last()).toHaveText(/Web Application Firewall/i);
await expect(cards.last().locator('.project-links')).not.toBeAttached();
// removed cards are gone from the grid
expect(titles).not.toContain('Self-Hosted Services');
expect(titles).not.toContain('Kubernetes Cluster');
});
```
2. `./build.sh && npm test` — rebuild and run the full suite.
## Testing & Quality
- Unit/integration: the new test covers (a) card count (6) and exact title
order, (b) Brain of Reese first with its Gitea source link, (c) Local AI
Stack tech tags (new + retained, no Ollama), (d) ServWaf last with no
source link, and (e) the two removed titles absent.
- Coverage: **>90%** on this task's new/modified code — test-only change;
the E2E suite is the binding gate.
## Completion Criteria
- [ ] the new test is present in `tests/e2e/01-page.spec.js` and passes
- [ ] `./build.sh && npm test` fully green (45 tests: 44 pre-existing + 1
new)
- [ ] README.md/AGENTS.md updated for anything user-visible this task changes
(the phase's final pass re-checks both project-wide)
- [ ] no behavior change in completed work
@@ -0,0 +1,11 @@
**Phase 01 — final verification pass (all criteria green)**
- Verified M-1 fix in `src/terminal.js`: ArrowUp / ArrowDown(`>0`) / ArrowDown-else now route through `updateDisplay()` (`textContent`); no `innerHTML` sink touches `cmdLine`/`commandHistory`.
- `grep -n innerHTML src/terminal.js` → 12 hits, all allowed (static prompt literals, `clear`/prank wipes, `outLine.innerHTML = output` gated on the static canned `neofetch` string). **C1 ✓**
- XSS regression test at `tests/e2e/02-terminal.spec.js:156` present + passing; re-proved it is a real guard: re-injected the old `innerHTML` recall into `dist/terminal.*.js` → test failed (`#xss-marker` received 1); rebuild → byte-identical to `src/`. **C2 ✓**
- `./build.sh` → `dist/` OK; `npm test` → **45 passed (0 failed)**; `bash .agents/validate.sh` → **exit 0** (suite + repo-hygiene gates). **C3 ✓**
- Branch coverage of modified code: all 3 recall arms asserted (ArrowUp ×2 specs, ArrowDown `>0` in the existing history spec, ArrowDown-else → empty prompt in the new spec) → >90% gate met; no JS coverage/lint toolchain exists in the locked stack, so lint = `node --check src/*.js tests/e2e/*.js playwright.config.js` + `bash -n build.sh .agents/validate.sh` — clean.
- C4 ✓ terminal/vim/achievements/menu specs all green; only the three recall branches changed.
- Docs (step 6, full README/AGENTS review): README — run section now states the image already contains the built `dist/` (mount `dist/`, never `src/`); new “Serving & configuration” section for `nginx.conf`, incl. **empirically measured** (built image on 127.0.0.1:8124) that `/`, `/index.html` and hashed assets currently return *only* cache headers — the `add_header` non-merge gap = finding M-4/Phase 03; TLS/HSTS-at-edge rule; Quadlet section fixed (unit is not in this repo; Quadlet generates `homepage.service`, so `… start homepage.service`, and `systemctl enable` is a no-op for transient Quadlet units → `[Install]` + `daemon-reload` + linger); Development gained the Node 20+ floor, `npx playwright install chromium`, and `.agents/validate.sh`. AGENTS.md — added the validate.sh gate, flagged `./scripts/check-headers.sh` as not yet in the repo (Phase 03), and scoped the M-1 rule with the allowed-`innerHTML` list.
- Notable: `.agents/PLAN.md` still says “44 tests” (3 places) and its §7 roadmap omits phases 04/05 — left untouched per the no-PLAN-edit rule; flag for the next PLAN review. No live-infra touched (temp podman image built/removed for the header measurement only).
- Next pending phase: `02_simulate_fetch_commands`.
@@ -0,0 +1,419 @@
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:10] "GET /index.html HTTP/1.1" 200 -
Running 45 tests using 1 worker
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:10] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:10] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:10] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:10] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:10] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:10] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:10] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:10] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 1 [chromium] › tests/e2e/01-page.spec.js:9:5 › Page structure › loads with correct title and lang (1.2s)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:11] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:11] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:11] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:11] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:11] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:11] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:11] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:11] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 2 [chromium] › tests/e2e/01-page.spec.js:14:5 › Page structure › nav has all seven section links pointing at existing targets (589ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:12] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:12] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:12] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:12] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:12] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:12] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:12] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:12] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 3 [chromium] › tests/e2e/01-page.spec.js:24:5 › Page structure › all major sections exist and are in the DOM (571ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:13] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:13] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:13] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:13] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:13] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:13] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:13] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:13] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 4 [chromium] › tests/e2e/01-page.spec.js:30:5 › Page structure › profile image loads (566ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:13] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:13] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:13] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:13] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:13] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:13] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:13] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:13] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 5 [chromium] › tests/e2e/01-page.spec.js:38:5 › Page structure › server rack background is generated with a terminal unit (481ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:14] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:14] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:14] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:14] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:14] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:14] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:14] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:14] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 6 [chromium] › tests/e2e/01-page.spec.js:45:5 › Page structure › GPG section shows both fingerprints and key blocks (501ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:14] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:14] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:14] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:14] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:14] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:14] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:14] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:14] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 7 [chromium] › tests/e2e/01-page.spec.js:59:5 › Page structure › external links all carry rel="noopener" (488ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:15] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:15] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:15] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:15] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:15] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:15] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:15] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:15] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:15] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
✓ 8 [chromium] › tests/e2e/01-page.spec.js:68:5 › Page structure › hashed assets are referenced and served (495ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:15] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:15] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:15] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:15] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:15] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:15] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:15] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:15] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 9 [chromium] › tests/e2e/02-terminal.spec.js:11:5 › Fake terminal — basic commands › hero click expands the terminal and shifts the hero (574ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:16] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:16] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:16] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:16] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:16] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:16] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:16] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:16] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 10 [chromium] › tests/e2e/02-terminal.spec.js:17:5 › Fake terminal — basic commands › initial boot lines are rendered (577ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:16] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:16] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:16] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:16] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:16] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:16] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:16] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:16] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 11 [chromium] › tests/e2e/02-terminal.spec.js:23:5 › Fake terminal — basic commands › uptime shows the load-average line (585ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:17] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:17] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:17] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:17] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:17] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:17] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:17] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:17] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 12 [chromium] › tests/e2e/02-terminal.spec.js:28:5 › Fake terminal — basic commands › ls lists the portfolio files (601ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:17] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:17] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:17] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:17] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:17] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:17] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:17] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:17] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 13 [chromium] › tests/e2e/02-terminal.spec.js:36:5 › Fake terminal — basic commands › pwd / whoami / hostname / id (658ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:18] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:18] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:18] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:18] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:18] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:18] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:18] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:18] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 14 [chromium] › tests/e2e/02-terminal.spec.js:47:5 › Fake terminal — basic commands › date shows a plausible current date (572ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:19] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:19] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:19] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:19] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:19] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:19] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:19] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:19] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 15 [chromium] › tests/e2e/02-terminal.spec.js:53:5 › Fake terminal — basic commands › uname and cat /etc/os-release (616ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:19] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:19] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:19] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:19] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:19] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:19] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:19] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:19] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 16 [chromium] › tests/e2e/02-terminal.spec.js:62:5 › Fake terminal — basic commands › echo prints its argument as plain text (559ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:20] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:20] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:20] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:20] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:20] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:20] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:20] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:20] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 17 [chromium] › tests/e2e/02-terminal.spec.js:67:5 › Fake terminal — basic commands › ss shows listening ports (566ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:20] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:20] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:20] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:20] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:20] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:20] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:20] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:20] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 18 [chromium] › tests/e2e/02-terminal.spec.js:74:5 › Fake terminal — basic commands › docker ps and podman ps (608ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:21] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:21] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:21] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:21] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:21] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:21] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:21] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:21] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 19 [chromium] › tests/e2e/02-terminal.spec.js:85:5 › Fake terminal — basic commands › ps aux and df -h and free -h (651ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:22] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:22] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:22] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:22] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:22] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:22] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:22] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:22] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 20 [chromium] › tests/e2e/02-terminal.spec.js:94:5 › Fake terminal — basic commands › neofetch renders the ASCII logo and colored blocks (606ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:22] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:22] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:22] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:22] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:22] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:22] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:22] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:22] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 21 [chromium] › tests/e2e/02-terminal.spec.js:102:5 › Fake terminal — basic commands › sl prints the locomotive (606ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:23] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:23] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:23] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:23] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:23] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:23] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:23] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:23] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 22 [chromium] › tests/e2e/02-terminal.spec.js:107:5 › Fake terminal — basic commands › help lists the available commands (595ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:24] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:24] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:24] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:24] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:24] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:24] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:24] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:24] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 23 [chromium] › tests/e2e/02-terminal.spec.js:115:5 › Fake terminal — basic commands › systemctl, ip addr, cat ssh key (651ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:24] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:24] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:24] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:24] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:24] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:24] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:24] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:24] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 24 [chromium] › tests/e2e/02-terminal.spec.js:124:5 › Fake terminal — basic commands › unknown command produces no output and a fresh prompt (548ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:25] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:25] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:25] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:25] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:25] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:25] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:25] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:25] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 25 [chromium] › tests/e2e/02-terminal.spec.js:139:5 › Fake terminal — state and special commands › history: ArrowUp/ArrowDown recall previous commands (626ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:25] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:25] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:25] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:25] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:25] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:25] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:25] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:25] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 26 [chromium] › tests/e2e/02-terminal.spec.js:156:5 › Fake terminal — state and special commands › history recall renders markup payloads as literal text (no DOM injection) (942ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:26] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:26] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:26] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:26] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:26] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:26] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:26] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:26] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 27 [chromium] › tests/e2e/02-terminal.spec.js:195:5 › Fake terminal — state and special commands › Tab completes a command (519ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:27] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:27] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:27] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:27] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:27] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:27] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:27] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:27] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 28 [chromium] › tests/e2e/02-terminal.spec.js:203:5 › Fake terminal — state and special commands › Tab cycles between multiple matches (560ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:27] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:27] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:27] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:27] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:27] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:27] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:27] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:27] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 29 [chromium] › tests/e2e/02-terminal.spec.js:218:5 › Fake terminal — state and special commands › clear empties the terminal and leaves one prompt line (610ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:28] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:28] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:28] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:28] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:28] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:28] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:28] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:28] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 30 [chromium] › tests/e2e/02-terminal.spec.js:226:5 › Fake terminal — state and special commands › sudo su - switches the prompt to root (#) (636ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:29] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:29] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:29] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:29] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:29] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:29] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:29] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:29] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 31 [chromium] › tests/e2e/02-terminal.spec.js:239:5 › Fake terminal — state and special commands › rm -rf / as a normal user is refused (609ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:29] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:29] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:29] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:29] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:29] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:29] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:29] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:29] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 32 [chromium] › tests/e2e/02-terminal.spec.js:247:5 › Fake terminal — state and special commands › rm -rf / as root triggers the destruction easter egg (1.3s)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:31] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:31] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:31] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:31] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:31] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:31] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:31] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:31] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 33 [chromium] › tests/e2e/02-terminal.spec.js:257:5 › Fake terminal — state and special commands › exit as a normal user swaps the page for a login screen (589ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:31] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:31] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:31] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:31] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:31] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:31] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:31] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:31] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 34 [chromium] › tests/e2e/02-terminal.spec.js:270:5 › Fake terminal — state and special commands › backspace edits the current command (598ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:32] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:32] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:32] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:32] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:32] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:32] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:32] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:32] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 35 [chromium] › tests/e2e/03-vim.spec.js:15:5 › Fake terminal — vim simulator › vim with no filename shows the splash and q exits (667ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:33] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:33] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:33] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:33] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:33] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:33] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:33] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:33] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 36 [chromium] › tests/e2e/03-vim.spec.js:26:5 › Fake terminal — vim simulator › vim with a filename opens a buffer; insert, save & quit (613ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:33] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:33] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:33] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:33] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:33] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:33] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:33] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:33] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 37 [chromium] › tests/e2e/03-vim.spec.js:48:5 › Fake terminal — vim simulator › vim normal-mode navigation and line deletion (668ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:34] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:34] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:34] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:34] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:34] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:34] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:34] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:34] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 38 [chromium] › tests/e2e/04-achievements.spec.js:8:5 › Achievements system › starts hidden until the first unlock (527ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:34] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:34] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:34] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:34] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:34] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:34] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:34] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:34] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 39 [chromium] › tests/e2e/04-achievements.spec.js:14:5 › Achievements system › uptime unlock shows a toast, persists to localStorage, reveals the section (589ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:35] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:35] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:35] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:35] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:35] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:35] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:35] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:35] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:36] "GET / HTTP/1.1" 304 -
✓ 40 [chromium] › tests/e2e/04-achievements.spec.js:43:5 › Achievements system › unlocks survive a page reload (localStorage restore) (689ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:36] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:36] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:36] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:36] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:36] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:36] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:36] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:36] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:36] "GET / HTTP/1.1" 304 -
✓ 41 [chromium] › tests/e2e/04-achievements.spec.js:55:5 › Achievements system › special achievements: sudo, nice-try rm, vim splash (761ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:36] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:36] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:36] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:36] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:36] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:36] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:36] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:36] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 42 [chromium] › tests/e2e/04-achievements.spec.js:80:5 › Achievements system › multiple unlocks stack toasts and increment the counter (629ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:37] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:37] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:37] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:37] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:37] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:37] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:37] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:37] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 43 [chromium] › tests/e2e/05-menu.spec.js:5:5 › Navigation menu › desktop: inline nav visible, hamburger hidden (552ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:38] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:38] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:38] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:38] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:38] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:38] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:38] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:38] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 44 [chromium] › tests/e2e/05-menu.spec.js:12:5 › Navigation menu › mobile: hamburger opens and closes the menu (1.8s)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:39] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:39] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:39] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:39] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:39] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:39] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:39] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:45:39] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 45 [chromium] › tests/e2e/05-menu.spec.js:30:5 › Navigation menu › clicking outside closes an open mobile menu (599ms)
45 passed (30.5s)
To open last HTML report run:

 npx playwright show-report

@@ -0,0 +1,19 @@
**Implemented**
- `src/terminal.js`: removed the DOM-XSS sink (audit M-1) from ArrowUp/ArrowDown history recall — all three `lastLine.innerHTML = '<span class="terminal-prompt">$</span> ' + cmdLine + ' '` blocks (incl. cursor `createElement`/`appendChild`) replaced by the existing text-only `updateDisplay()` path: `updateDisplay(cmdLine)` (ArrowUp, ArrowDown first case) and `updateDisplay('')` (ArrowDown → `historyIndex = -1`). −20/+5 lines; no other file touched.
- Verified side effects match the task's two intended improvements: recalled prompt now has no trailing space and renders `#` + red cursor after `sudo su -`.
**Tests / lint / coverage (all green)**
- `./build.sh` → `dist/` rebuilt.
- `npm test` → **44 passed** (29–30s), incl. `02-terminal.spec.js › history: ArrowUp/ArrowDown recall previous commands`.
- `bash .agents/validate.sh` → **exit 0** (44 passed + repo-hygiene gates clean).
- Lint: no JS linter in the locked stack; `node --check` clean on all `src/*.js`, `tests/e2e/*.js`, `playwright.config.js`.
- Coverage of modified code measured with V8 precise coverage (CDP, throwaway script) driven only by the existing history-test flows: **3/3 modified branch statements hit (100%)**, > 90% gate met.
- Negative control: re-injecting the old `innerHTML` recall into a copy of `dist/` produced a live `<b id="xss-marker">` node (1); the fixed build produces **0** DOM nodes, **0** `<img>` nodes and no script execution for `<b id=xss-marker>` / `<img src=x onerror=…>` payloads, while `whoami` is still recalled and executable (`reese`).
**Docs:** no doc impact — no user-visible commands, setup, config or conventions changed (`README.md`/`AGENTS.md` untouched; pre-existing working-tree edits from the Playwright re-pin left as-is).
**Decisions / notes**
- Kept the fix strictly in the task's scope; `innerHTML` remaining in `terminal.js` is only static prompt literals, `clear`/body wipes, and the `neofetch` canned output (all explicitly allowed). `grep -n innerHTML src/terminal.js | grep -iE 'cmdline|history'` → no hits.
- Pre-existing quirk left unchanged (out of scope, behavior-identical to before): recall does not sync `mobileInput.value`/`lastInputValue`, so typing *after* a recall appends to the recalled line. Worth a follow-up phase if the owner wants editable recalls.
**Next pending task:** `.agents/phases/todo/01_fix_history_xss/02_xss_regression_test.md`
@@ -0,0 +1,410 @@
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:56:58] "GET /index.html HTTP/1.1" 200 -
Running 44 tests using 1 worker
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:56:58] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:56:58] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:56:58] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:56:58] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:56:58] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:56:58] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:56:58] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:56:58] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 1 [chromium] › tests/e2e/01-page.spec.js:9:5 › Page structure › loads with correct title and lang (1.1s)
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:00] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:00] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:00] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:00] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:00] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:00] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:00] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:00] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 2 [chromium] › tests/e2e/01-page.spec.js:14:5 › Page structure › nav has all seven section links pointing at existing targets (540ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:00] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:00] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:00] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:00] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:00] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:00] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:00] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:00] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 3 [chromium] › tests/e2e/01-page.spec.js:24:5 › Page structure › all major sections exist and are in the DOM (557ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:01] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:01] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:01] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:01] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:01] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:01] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:01] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:01] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 4 [chromium] › tests/e2e/01-page.spec.js:30:5 › Page structure › profile image loads (570ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:01] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:01] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:01] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:01] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:01] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:01] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:01] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:01] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 5 [chromium] › tests/e2e/01-page.spec.js:38:5 › Page structure › server rack background is generated with a terminal unit (568ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:02] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:02] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:02] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:02] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:02] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:02] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:02] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:02] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 6 [chromium] › tests/e2e/01-page.spec.js:45:5 › Page structure › GPG section shows both fingerprints and key blocks (556ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:02] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:02] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:02] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:02] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:02] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:02] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:02] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:02] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 7 [chromium] › tests/e2e/01-page.spec.js:59:5 › Page structure › external links all carry rel="noopener" (552ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:03] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:03] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:03] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:03] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:03] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:03] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:03] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:03] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:04] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
✓ 8 [chromium] › tests/e2e/01-page.spec.js:68:5 › Page structure › hashed assets are referenced and served (572ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:04] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:04] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:04] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:04] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:04] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:04] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:04] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:04] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 9 [chromium] › tests/e2e/02-terminal.spec.js:11:5 › Fake terminal — basic commands › hero click expands the terminal and shifts the hero (557ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:04] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:04] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:04] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:04] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:04] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:04] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:04] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:04] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 10 [chromium] › tests/e2e/02-terminal.spec.js:17:5 › Fake terminal — basic commands › initial boot lines are rendered (610ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:05] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:05] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:05] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:05] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:05] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:05] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:05] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:05] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 11 [chromium] › tests/e2e/02-terminal.spec.js:23:5 › Fake terminal — basic commands › uptime shows the load-average line (627ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:05] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:05] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:05] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:05] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:05] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:05] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:05] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:05] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 12 [chromium] › tests/e2e/02-terminal.spec.js:28:5 › Fake terminal — basic commands › ls lists the portfolio files (701ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:06] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:06] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:06] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:06] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:06] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:06] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:06] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:06] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
✓ 13 [chromium] › tests/e2e/02-terminal.spec.js:36:5 › Fake terminal — basic commands › pwd / whoami / hostname / id (809ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:07] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:07] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:07] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:07] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:07] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:07] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:07] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:07] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 14 [chromium] › tests/e2e/02-terminal.spec.js:47:5 › Fake terminal — basic commands › date shows a plausible current date (595ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:08] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:08] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:08] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:08] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:08] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:08] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:08] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:08] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 15 [chromium] › tests/e2e/02-terminal.spec.js:53:5 › Fake terminal — basic commands › uname and cat /etc/os-release (614ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:08] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:08] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:08] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:08] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:08] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:08] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:08] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:08] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 16 [chromium] › tests/e2e/02-terminal.spec.js:62:5 › Fake terminal — basic commands › echo prints its argument as plain text (597ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:09] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:09] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:09] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:09] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:09] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:09] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:09] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:09] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 17 [chromium] › tests/e2e/02-terminal.spec.js:67:5 › Fake terminal — basic commands › ss shows listening ports (570ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:09] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:09] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:09] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:09] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:09] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:09] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:09] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:09] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 18 [chromium] › tests/e2e/02-terminal.spec.js:74:5 › Fake terminal — basic commands › docker ps and podman ps (602ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:10] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:10] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:10] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:10] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:10] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:10] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:10] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:10] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 19 [chromium] › tests/e2e/02-terminal.spec.js:85:5 › Fake terminal — basic commands › ps aux and df -h and free -h (633ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:11] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:11] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:11] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:11] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:11] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:11] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:11] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:11] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 20 [chromium] › tests/e2e/02-terminal.spec.js:94:5 › Fake terminal — basic commands › neofetch renders the ASCII logo and colored blocks (612ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:11] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:11] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:11] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:11] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:11] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:11] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:11] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:11] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 21 [chromium] › tests/e2e/02-terminal.spec.js:102:5 › Fake terminal — basic commands › sl prints the locomotive (580ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:12] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:12] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:12] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:12] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:12] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:12] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:12] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:12] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 22 [chromium] › tests/e2e/02-terminal.spec.js:107:5 › Fake terminal — basic commands › help lists the available commands (607ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:12] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:12] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:12] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:12] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:12] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:12] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:12] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:12] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 23 [chromium] › tests/e2e/02-terminal.spec.js:115:5 › Fake terminal — basic commands › systemctl, ip addr, cat ssh key (744ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:13] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:13] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:13] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:13] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:13] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:13] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:13] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:13] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 24 [chromium] › tests/e2e/02-terminal.spec.js:124:5 › Fake terminal — basic commands › unknown command produces no output and a fresh prompt (667ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:14] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:14] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:14] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:14] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:14] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:14] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:14] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:14] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 25 [chromium] › tests/e2e/02-terminal.spec.js:139:5 › Fake terminal — state and special commands › history: ArrowUp/ArrowDown recall previous commands (664ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:14] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:14] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:14] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:14] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:14] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:14] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:14] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:14] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 26 [chromium] › tests/e2e/02-terminal.spec.js:153:5 › Fake terminal — state and special commands › Tab completes a command (636ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:15] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:15] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:15] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:15] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:15] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:15] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:15] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:15] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 27 [chromium] › tests/e2e/02-terminal.spec.js:161:5 › Fake terminal — state and special commands › Tab cycles between multiple matches (610ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:16] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:16] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:16] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:16] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:16] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:16] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:16] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:16] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 28 [chromium] › tests/e2e/02-terminal.spec.js:176:5 › Fake terminal — state and special commands › clear empties the terminal and leaves one prompt line (608ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:16] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:16] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:16] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:16] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:16] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:16] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:16] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:16] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 29 [chromium] › tests/e2e/02-terminal.spec.js:184:5 › Fake terminal — state and special commands › sudo su - switches the prompt to root (#) (644ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:17] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:17] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:17] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:17] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:17] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:17] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:17] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:17] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 30 [chromium] › tests/e2e/02-terminal.spec.js:197:5 › Fake terminal — state and special commands › rm -rf / as a normal user is refused (602ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:18] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:18] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:18] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:18] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:18] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:18] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:18] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:18] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 31 [chromium] › tests/e2e/02-terminal.spec.js:205:5 › Fake terminal — state and special commands › rm -rf / as root triggers the destruction easter egg (1.3s)
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:19] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:19] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:19] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:19] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:19] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:19] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:19] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:19] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 32 [chromium] › tests/e2e/02-terminal.spec.js:215:5 › Fake terminal — state and special commands › exit as a normal user swaps the page for a login screen (589ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:20] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:20] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:20] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:20] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:20] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:20] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:20] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:20] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 33 [chromium] › tests/e2e/02-terminal.spec.js:228:5 › Fake terminal — state and special commands › backspace edits the current command (616ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:20] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:20] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:20] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:20] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:20] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:20] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:20] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:20] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 34 [chromium] › tests/e2e/03-vim.spec.js:15:5 › Fake terminal — vim simulator › vim with no filename shows the splash and q exits (669ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:21] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:21] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:21] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:21] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:21] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:21] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:21] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:21] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 35 [chromium] › tests/e2e/03-vim.spec.js:26:5 › Fake terminal — vim simulator › vim with a filename opens a buffer; insert, save & quit (706ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:22] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:22] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:22] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:22] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:22] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:22] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:22] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:22] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 36 [chromium] › tests/e2e/03-vim.spec.js:48:5 › Fake terminal — vim simulator › vim normal-mode navigation and line deletion (684ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:22] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:22] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:22] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:22] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:22] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:22] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:22] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:22] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 37 [chromium] › tests/e2e/04-achievements.spec.js:8:5 › Achievements system › starts hidden until the first unlock (545ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:23] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:23] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:23] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:23] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:23] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:23] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:23] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:23] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 38 [chromium] › tests/e2e/04-achievements.spec.js:14:5 › Achievements system › uptime unlock shows a toast, persists to localStorage, reveals the section (622ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:23] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:23] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:23] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:23] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:23] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:23] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:23] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:23] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:24] "GET / HTTP/1.1" 304 -
✓ 39 [chromium] › tests/e2e/04-achievements.spec.js:43:5 › Achievements system › unlocks survive a page reload (localStorage restore) (649ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:24] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:24] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:24] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:24] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:24] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:24] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:24] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:24] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:25] "GET / HTTP/1.1" 304 -
✓ 40 [chromium] › tests/e2e/04-achievements.spec.js:55:5 › Achievements system › special achievements: sudo, nice-try rm, vim splash (788ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:25] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:25] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:25] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:25] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:25] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:25] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:25] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:25] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 41 [chromium] › tests/e2e/04-achievements.spec.js:80:5 › Achievements system › multiple unlocks stack toasts and increment the counter (633ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:25] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:25] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:25] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:25] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:25] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:25] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:25] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:25] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 42 [chromium] › tests/e2e/05-menu.spec.js:5:5 › Navigation menu › desktop: inline nav visible, hamburger hidden (540ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:26] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:26] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:26] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:26] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:26] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:26] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:26] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:26] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 43 [chromium] › tests/e2e/05-menu.spec.js:12:5 › Navigation menu › mobile: hamburger opens and closes the menu (1.8s)
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:28] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:28] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:28] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:28] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:28] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:28] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:28] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 21:57:28] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 44 [chromium] › tests/e2e/05-menu.spec.js:30:5 › Navigation menu › clicking outside closes an open mobile menu (667ms)
44 passed (30.6s)
To open last HTML report run:

 npx playwright show-report

@@ -0,0 +1 @@
(no final assistant message — see the .err log)
@@ -0,0 +1 @@
error: assistant error: litellm.APIConnectionError: APIConnectionError: OpenAIException - Response payload is not completed: <TransferEncodingError: 400, message='Not…
@@ -0,0 +1,419 @@
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:01] "GET /index.html HTTP/1.1" 200 -
Running 45 tests using 1 worker
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:01] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:01] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:01] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:01] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:01] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:01] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:01] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:01] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 1 [chromium] › tests/e2e/01-page.spec.js:9:5 › Page structure › loads with correct title and lang (1.1s)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:02] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:02] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:02] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:02] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:02] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:02] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:02] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:02] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 2 [chromium] › tests/e2e/01-page.spec.js:14:5 › Page structure › nav has all seven section links pointing at existing targets (559ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:03] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:03] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:03] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:03] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:03] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:03] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:03] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:03] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 3 [chromium] › tests/e2e/01-page.spec.js:24:5 › Page structure › all major sections exist and are in the DOM (487ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:03] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:03] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:03] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:03] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:03] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:03] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:03] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:03] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 4 [chromium] › tests/e2e/01-page.spec.js:30:5 › Page structure › profile image loads (519ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:04] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:04] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:04] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:04] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:04] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:04] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:04] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:04] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 5 [chromium] › tests/e2e/01-page.spec.js:38:5 › Page structure › server rack background is generated with a terminal unit (524ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:04] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:04] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:04] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:04] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:04] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:04] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:04] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:04] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 6 [chromium] › tests/e2e/01-page.spec.js:45:5 › Page structure › GPG section shows both fingerprints and key blocks (602ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:05] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:05] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:05] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:05] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:05] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:05] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:05] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:05] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 7 [chromium] › tests/e2e/01-page.spec.js:59:5 › Page structure › external links all carry rel="noopener" (621ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:06] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:06] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:06] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:06] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:06] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:06] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:06] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:06] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:06] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
✓ 8 [chromium] › tests/e2e/01-page.spec.js:68:5 › Page structure › hashed assets are referenced and served (523ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:06] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:06] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:06] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:06] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:06] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:06] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:06] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:06] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 9 [chromium] › tests/e2e/02-terminal.spec.js:11:5 › Fake terminal — basic commands › hero click expands the terminal and shifts the hero (571ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:07] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:07] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:07] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:07] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:07] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:07] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:07] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:07] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 10 [chromium] › tests/e2e/02-terminal.spec.js:17:5 › Fake terminal — basic commands › initial boot lines are rendered (578ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:07] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:07] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:07] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:07] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:07] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:07] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:07] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:07] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 11 [chromium] › tests/e2e/02-terminal.spec.js:23:5 › Fake terminal — basic commands › uptime shows the load-average line (605ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:08] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:08] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:08] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:08] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:08] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:08] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:08] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:08] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 12 [chromium] › tests/e2e/02-terminal.spec.js:28:5 › Fake terminal — basic commands › ls lists the portfolio files (595ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:09] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:09] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:09] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:09] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:09] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:09] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:09] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:09] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 13 [chromium] › tests/e2e/02-terminal.spec.js:36:5 › Fake terminal — basic commands › pwd / whoami / hostname / id (643ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:09] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:09] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:09] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:09] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:09] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:09] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:09] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:09] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 14 [chromium] › tests/e2e/02-terminal.spec.js:47:5 › Fake terminal — basic commands › date shows a plausible current date (673ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:10] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:10] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:10] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:10] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:10] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:10] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:10] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:10] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 15 [chromium] › tests/e2e/02-terminal.spec.js:53:5 › Fake terminal — basic commands › uname and cat /etc/os-release (626ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:11] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:11] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:11] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:11] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:11] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:11] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:11] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:11] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 16 [chromium] › tests/e2e/02-terminal.spec.js:62:5 › Fake terminal — basic commands › echo prints its argument as plain text (684ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:11] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:11] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:11] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:11] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:11] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:11] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:11] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:11] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 17 [chromium] › tests/e2e/02-terminal.spec.js:67:5 › Fake terminal — basic commands › ss shows listening ports (655ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:12] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:12] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:12] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:12] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:12] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:12] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:12] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:12] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 18 [chromium] › tests/e2e/02-terminal.spec.js:74:5 › Fake terminal — basic commands › docker ps and podman ps (721ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:13] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:13] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:13] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:13] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:13] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:13] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:13] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:13] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 19 [chromium] › tests/e2e/02-terminal.spec.js:85:5 › Fake terminal — basic commands › ps aux and df -h and free -h (781ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:13] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:13] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:13] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:13] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:13] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:13] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:13] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:13] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
✓ 20 [chromium] › tests/e2e/02-terminal.spec.js:94:5 › Fake terminal — basic commands › neofetch renders the ASCII logo and colored blocks (600ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:14] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:14] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:14] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:14] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:14] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:14] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:14] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:14] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 21 [chromium] › tests/e2e/02-terminal.spec.js:102:5 › Fake terminal — basic commands › sl prints the locomotive (508ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:15] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:15] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:15] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:15] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:15] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:15] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:15] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:15] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 22 [chromium] › tests/e2e/02-terminal.spec.js:107:5 › Fake terminal — basic commands › help lists the available commands (585ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:15] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:15] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:15] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:15] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:15] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:15] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:15] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:15] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 23 [chromium] › tests/e2e/02-terminal.spec.js:115:5 › Fake terminal — basic commands › systemctl, ip addr, cat ssh key (703ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:16] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:16] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:16] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:16] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:16] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:16] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:16] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:16] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 24 [chromium] › tests/e2e/02-terminal.spec.js:124:5 › Fake terminal — basic commands › unknown command produces no output and a fresh prompt (536ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:16] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:16] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:16] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:16] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:16] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:16] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:16] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:16] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 25 [chromium] › tests/e2e/02-terminal.spec.js:139:5 › Fake terminal — state and special commands › history: ArrowUp/ArrowDown recall previous commands (637ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:17] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:17] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:17] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:17] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:17] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:17] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:17] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:17] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 26 [chromium] › tests/e2e/02-terminal.spec.js:156:5 › Fake terminal — state and special commands › history recall renders markup payloads as literal text (no DOM injection) (916ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:18] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:18] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:18] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:18] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:18] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:18] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:18] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:18] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 27 [chromium] › tests/e2e/02-terminal.spec.js:195:5 › Fake terminal — state and special commands › Tab completes a command (501ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:18] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:18] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:18] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:18] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:18] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:18] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:18] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:18] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 28 [chromium] › tests/e2e/02-terminal.spec.js:203:5 › Fake terminal — state and special commands › Tab cycles between multiple matches (605ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:19] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:19] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:19] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:19] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:19] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:19] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:19] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:19] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 29 [chromium] › tests/e2e/02-terminal.spec.js:218:5 › Fake terminal — state and special commands › clear empties the terminal and leaves one prompt line (588ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:20] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:20] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:20] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:20] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:20] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:20] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:20] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:20] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 30 [chromium] › tests/e2e/02-terminal.spec.js:226:5 › Fake terminal — state and special commands › sudo su - switches the prompt to root (#) (565ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:20] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:20] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:20] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:20] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:20] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:20] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:20] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:20] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 31 [chromium] › tests/e2e/02-terminal.spec.js:239:5 › Fake terminal — state and special commands › rm -rf / as a normal user is refused (598ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:21] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:21] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:21] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:21] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:21] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:21] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:21] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:21] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 32 [chromium] › tests/e2e/02-terminal.spec.js:247:5 › Fake terminal — state and special commands › rm -rf / as root triggers the destruction easter egg (1.3s)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:22] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:22] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:22] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:22] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:22] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:22] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:22] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:22] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 33 [chromium] › tests/e2e/02-terminal.spec.js:257:5 › Fake terminal — state and special commands › exit as a normal user swaps the page for a login screen (563ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:23] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:23] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:23] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:23] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:23] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:23] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:23] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:23] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 34 [chromium] › tests/e2e/02-terminal.spec.js:270:5 › Fake terminal — state and special commands › backspace edits the current command (580ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:23] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:23] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:23] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:23] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:23] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:23] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:23] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:23] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 35 [chromium] › tests/e2e/03-vim.spec.js:15:5 › Fake terminal — vim simulator › vim with no filename shows the splash and q exits (664ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:24] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:24] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:24] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:24] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:24] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:24] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:24] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:24] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 36 [chromium] › tests/e2e/03-vim.spec.js:26:5 › Fake terminal — vim simulator › vim with a filename opens a buffer; insert, save & quit (558ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:25] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:25] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:25] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:25] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:25] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:25] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:25] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:25] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 37 [chromium] › tests/e2e/03-vim.spec.js:48:5 › Fake terminal — vim simulator › vim normal-mode navigation and line deletion (685ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:25] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:25] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:25] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:25] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:25] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:25] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:25] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:25] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 38 [chromium] › tests/e2e/04-achievements.spec.js:8:5 › Achievements system › starts hidden until the first unlock (527ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:26] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:26] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:26] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:26] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:26] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:26] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:26] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:26] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 39 [chromium] › tests/e2e/04-achievements.spec.js:14:5 › Achievements system › uptime unlock shows a toast, persists to localStorage, reveals the section (569ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:26] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:26] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:26] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:26] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:26] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:26] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:26] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:26] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:27] "GET / HTTP/1.1" 304 -
✓ 40 [chromium] › tests/e2e/04-achievements.spec.js:43:5 › Achievements system › unlocks survive a page reload (localStorage restore) (654ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:27] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:27] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:27] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:27] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:27] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:27] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:27] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:27] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:28] "GET / HTTP/1.1" 304 -
✓ 41 [chromium] › tests/e2e/04-achievements.spec.js:55:5 › Achievements system › special achievements: sudo, nice-try rm, vim splash (689ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:28] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:28] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:28] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:28] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:28] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:28] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:28] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:28] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 42 [chromium] › tests/e2e/04-achievements.spec.js:80:5 › Achievements system › multiple unlocks stack toasts and increment the counter (618ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:28] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:28] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:28] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:28] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:28] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:28] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:28] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:28] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 43 [chromium] › tests/e2e/05-menu.spec.js:5:5 › Navigation menu › desktop: inline nav visible, hamburger hidden (515ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:29] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:29] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:29] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:29] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:29] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:29] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:29] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:29] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 44 [chromium] › tests/e2e/05-menu.spec.js:12:5 › Navigation menu › mobile: hamburger opens and closes the menu (1.8s)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:31] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:31] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:31] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:31] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:31] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:31] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:31] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:14:31] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 45 [chromium] › tests/e2e/05-menu.spec.js:30:5 › Navigation menu › clicking outside closes an open mobile menu (549ms)
45 passed (30.8s)
To open last HTML report run:

 npx playwright show-report

@@ -0,0 +1,19 @@
**Implemented**
- `tests/e2e/02-terminal.spec.js`: added `history recall renders markup payloads as literal text (no DOM injection)` (in the *state and special commands* describe) covering (a) `<b id="xss-marker">pwned</b>` → recalled as exact literal text, `#xss-marker` and `.terminal-content b` count 0; (b) `<img src="data:," onerror=…>` → `window.__xssFired === false`, no `img[onerror]`, literal text; (c) benign `whoami` recalled and re-executed (`reese`).
- Step 3 adapted per the task note: ArrowDown (→ `updateDisplay('')`) first returns the line to an empty prompt before typing (recall does not sync `mobileInput`, so typing straight after a recall concatenates — pre-existing quirk, left unchanged); the payload assertions are exact-text instead of substring.
**Tests / lint / coverage (100% green)**
- `./build.sh` → `dist/` rebuilt; `npm test` → **45 passed** (30s); `bash .agents/validate.sh` → **exit 0** (45 passed + hygiene gates clean).
- Regression-guard proof: re-injecting the old `innerHTML` recall into the built `dist/terminal.*.js` makes the new test **fail** (`#xss-marker` received 1); a throwaway spec showed `__xssFired === true` there (the `data:,` arm is meaningful, no network). Rebuilt → identical to `src/`, suite green again.
- Coverage of modified code: V8 precise coverage over `src/terminal.js` L113–140 → 3/3 ranges hit (100%); all three recall arms are exercised with assertions — ArrowUp recall (both history tests), ArrowDown `historyIndex > 0` (existing test), ArrowDown else/`updateDisplay('')` (new test asserts an empty prompt) → >90% gate met.
- Lint: `node --check` clean on `src/*.js`, `tests/e2e/*.js`, `playwright.config.js`; `bash -n build.sh .agents/validate.sh` clean (no JS linter exists in the locked stack).
**Docs**
- `README.md`: documented the real dev loop (`npm install` / `./build.sh` / `npm test` on 127.0.0.1:8123, artifact-under-test = `dist/`), listed the terminal modules + flat-`src` rule, fixed the run command to mount `./dist` (mounting `./src` served unhashed names the rewritten `index.html` never requests), and noted `homepage.container` is not in this repo.
- `AGENTS.md`: new convention — terminal input/history must never reach `innerHTML`; use `updateDisplay()`/`textContent` (M-1, guarded by the new test).
**Notes/deviations**
- `grep -n innerHTML src/terminal.js | grep -iE 'cmdline|history'` → no hits (remaining uses are static prompt literals, clear/body wipes, neofetch canned output — all allowed).
- `.agents/PLAN.md` still says "44 tests" (§4/§5); left untouched per the no-PLAN-edits rule — the count is now 45, worth folding into the next PLAN review.
**Next pending task:** `.agents/phases/todo/02_simulate_fetch_commands/01_simulate_fetch_output.md` (phase 01's tasks are complete).
@@ -0,0 +1,419 @@
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:03] "GET /index.html HTTP/1.1" 200 -
Running 45 tests using 1 worker
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:04] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:04] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:04] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:04] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:04] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:04] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:04] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:04] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 1 [chromium] › tests/e2e/01-page.spec.js:9:5 › Page structure › loads with correct title and lang (616ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:04] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:04] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:04] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:04] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:04] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:04] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:04] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:04] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 2 [chromium] › tests/e2e/01-page.spec.js:14:5 › Page structure › nav has all seven section links pointing at existing targets (597ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:05] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:05] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:05] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:05] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:05] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:05] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:05] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:05] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 3 [chromium] › tests/e2e/01-page.spec.js:24:5 › Page structure › all major sections exist and are in the DOM (560ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:06] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:06] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:06] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:06] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:06] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:06] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:06] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:06] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 4 [chromium] › tests/e2e/01-page.spec.js:30:5 › Page structure › profile image loads (552ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:06] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:06] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:06] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:06] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:06] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:06] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:06] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:06] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 5 [chromium] › tests/e2e/01-page.spec.js:38:5 › Page structure › server rack background is generated with a terminal unit (562ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:07] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:07] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:07] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:07] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:07] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:07] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:07] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:07] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 6 [chromium] › tests/e2e/01-page.spec.js:45:5 › Page structure › GPG section shows both fingerprints and key blocks (561ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:07] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:07] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:07] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:07] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:07] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:07] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:07] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:07] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 7 [chromium] › tests/e2e/01-page.spec.js:59:5 › Page structure › external links all carry rel="noopener" (582ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:08] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:08] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:08] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:08] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:08] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:08] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:08] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:08] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:08] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
✓ 8 [chromium] › tests/e2e/01-page.spec.js:68:5 › Page structure › hashed assets are referenced and served (535ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:08] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:08] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:08] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:08] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:08] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:08] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:08] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:08] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 9 [chromium] › tests/e2e/02-terminal.spec.js:11:5 › Fake terminal — basic commands › hero click expands the terminal and shifts the hero (612ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:09] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:09] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:09] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:09] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:09] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:09] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:09] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:09] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 10 [chromium] › tests/e2e/02-terminal.spec.js:17:5 › Fake terminal — basic commands › initial boot lines are rendered (634ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:10] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:10] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:10] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:10] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:10] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:10] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:10] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:10] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 11 [chromium] › tests/e2e/02-terminal.spec.js:23:5 › Fake terminal — basic commands › uptime shows the load-average line (595ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:10] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:10] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:10] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:10] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:10] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:10] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:10] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:10] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 12 [chromium] › tests/e2e/02-terminal.spec.js:28:5 › Fake terminal — basic commands › ls lists the portfolio files (661ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:11] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:11] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:11] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:11] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:11] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:11] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:11] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:11] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 13 [chromium] › tests/e2e/02-terminal.spec.js:36:5 › Fake terminal — basic commands › pwd / whoami / hostname / id (719ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:12] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:12] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:12] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:12] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:12] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:12] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:12] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:12] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 14 [chromium] › tests/e2e/02-terminal.spec.js:47:5 › Fake terminal — basic commands › date shows a plausible current date (623ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:12] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:12] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:12] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:12] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:12] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:12] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:12] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:12] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 15 [chromium] › tests/e2e/02-terminal.spec.js:53:5 › Fake terminal — basic commands › uname and cat /etc/os-release (719ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:13] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:13] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:13] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:13] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:13] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:13] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:13] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:13] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 16 [chromium] › tests/e2e/02-terminal.spec.js:62:5 › Fake terminal — basic commands › echo prints its argument as plain text (611ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:14] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:14] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:14] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:14] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:14] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:14] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:14] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:14] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 17 [chromium] › tests/e2e/02-terminal.spec.js:67:5 › Fake terminal — basic commands › ss shows listening ports (587ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:14] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:14] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:14] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:14] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:14] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:14] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:14] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:14] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 18 [chromium] › tests/e2e/02-terminal.spec.js:74:5 › Fake terminal — basic commands › docker ps and podman ps (676ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:15] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:15] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:15] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:15] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:15] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:15] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:15] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:15] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 19 [chromium] › tests/e2e/02-terminal.spec.js:85:5 › Fake terminal — basic commands › ps aux and df -h and free -h (676ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:16] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:16] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:16] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:16] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:16] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:16] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:16] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:16] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 20 [chromium] › tests/e2e/02-terminal.spec.js:94:5 › Fake terminal — basic commands › neofetch renders the ASCII logo and colored blocks (630ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:16] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:16] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:16] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:16] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:16] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:16] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:16] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:16] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
✓ 21 [chromium] › tests/e2e/02-terminal.spec.js:102:5 › Fake terminal — basic commands › sl prints the locomotive (624ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:17] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:17] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:17] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:17] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:17] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:17] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:17] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:17] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 22 [chromium] › tests/e2e/02-terminal.spec.js:107:5 › Fake terminal — basic commands › help lists the available commands (596ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:17] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:17] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:17] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:17] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:17] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:17] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:17] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:17] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 23 [chromium] › tests/e2e/02-terminal.spec.js:115:5 › Fake terminal — basic commands › systemctl, ip addr, cat ssh key (688ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:18] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:18] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:18] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:18] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:18] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:18] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:18] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:18] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 24 [chromium] › tests/e2e/02-terminal.spec.js:124:5 › Fake terminal — basic commands › unknown command produces no output and a fresh prompt (679ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:19] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:19] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:19] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:19] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:19] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:19] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:19] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:19] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 25 [chromium] › tests/e2e/02-terminal.spec.js:139:5 › Fake terminal — state and special commands › history: ArrowUp/ArrowDown recall previous commands (690ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:20] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:20] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:20] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:20] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:20] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:20] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:20] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:20] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 26 [chromium] › tests/e2e/02-terminal.spec.js:156:5 › Fake terminal — state and special commands › history recall renders markup payloads as literal text (no DOM injection) (1.0s)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:21] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:21] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:21] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:21] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:21] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:21] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:21] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:21] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 27 [chromium] › tests/e2e/02-terminal.spec.js:195:5 › Fake terminal — state and special commands › Tab completes a command (633ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:21] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:21] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:21] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:21] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:21] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:21] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:21] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:21] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 28 [chromium] › tests/e2e/02-terminal.spec.js:203:5 › Fake terminal — state and special commands › Tab cycles between multiple matches (570ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:22] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:22] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:22] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:22] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:22] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:22] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:22] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:22] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 29 [chromium] › tests/e2e/02-terminal.spec.js:218:5 › Fake terminal — state and special commands › clear empties the terminal and leaves one prompt line (593ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:22] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:22] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:22] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:22] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:22] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:22] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:22] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:22] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 30 [chromium] › tests/e2e/02-terminal.spec.js:226:5 › Fake terminal — state and special commands › sudo su - switches the prompt to root (#) (720ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:23] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:23] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:23] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:23] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:23] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:23] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:23] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:23] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 31 [chromium] › tests/e2e/02-terminal.spec.js:239:5 › Fake terminal — state and special commands › rm -rf / as a normal user is refused (697ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:24] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:24] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:24] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:24] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:24] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:24] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:24] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:24] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 32 [chromium] › tests/e2e/02-terminal.spec.js:247:5 › Fake terminal — state and special commands › rm -rf / as root triggers the destruction easter egg (1.2s)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:25] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:25] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:25] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:25] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:25] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:25] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:25] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:25] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 33 [chromium] › tests/e2e/02-terminal.spec.js:257:5 › Fake terminal — state and special commands › exit as a normal user swaps the page for a login screen (525ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:26] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:26] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:26] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:26] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:26] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:26] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:26] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:26] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 34 [chromium] › tests/e2e/02-terminal.spec.js:270:5 › Fake terminal — state and special commands › backspace edits the current command (533ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:26] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:26] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:26] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:26] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:26] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:26] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:26] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:26] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 35 [chromium] › tests/e2e/03-vim.spec.js:15:5 › Fake terminal — vim simulator › vim with no filename shows the splash and q exits (602ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:27] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:27] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:27] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:27] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:27] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:27] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:27] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:27] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 36 [chromium] › tests/e2e/03-vim.spec.js:26:5 › Fake terminal — vim simulator › vim with a filename opens a buffer; insert, save & quit (670ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:27] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:27] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:27] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:27] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:27] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:27] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:27] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:27] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 37 [chromium] › tests/e2e/03-vim.spec.js:48:5 › Fake terminal — vim simulator › vim normal-mode navigation and line deletion (598ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:28] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:28] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:28] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:28] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:28] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:28] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:28] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:28] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 38 [chromium] › tests/e2e/04-achievements.spec.js:8:5 › Achievements system › starts hidden until the first unlock (454ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:29] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:29] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:29] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:29] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:29] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:29] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:29] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:29] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 39 [chromium] › tests/e2e/04-achievements.spec.js:14:5 › Achievements system › uptime unlock shows a toast, persists to localStorage, reveals the section (661ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:29] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:29] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:29] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:29] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:29] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:29] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:29] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:29] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:30] "GET / HTTP/1.1" 304 -
✓ 40 [chromium] › tests/e2e/04-achievements.spec.js:43:5 › Achievements system › unlocks survive a page reload (localStorage restore) (589ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:30] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:30] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:30] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:30] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:30] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:30] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:30] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:30] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:30] "GET / HTTP/1.1" 304 -
✓ 41 [chromium] › tests/e2e/04-achievements.spec.js:55:5 › Achievements system › special achievements: sudo, nice-try rm, vim splash (647ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:30] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:30] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:30] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:30] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:30] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:30] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:30] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:30] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 42 [chromium] › tests/e2e/04-achievements.spec.js:80:5 › Achievements system › multiple unlocks stack toasts and increment the counter (645ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:31] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:31] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:31] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:31] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:31] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:31] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:31] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:31] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 43 [chromium] › tests/e2e/05-menu.spec.js:5:5 › Navigation menu › desktop: inline nav visible, hamburger hidden (470ms)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:32] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:32] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:32] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:32] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:32] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:32] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:32] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:32] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 44 [chromium] › tests/e2e/05-menu.spec.js:12:5 › Navigation menu › mobile: hamburger opens and closes the menu (1.8s)
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:33] "GET / HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:33] "GET /terminal-commands.54dfa2e744e31eb4eb25d6ff72a4f909.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:33] "GET /terminal.ee4989b043e6389cf0b8619343b6d0f9.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:33] "GET /terminal-achievements.824b6020d4572150826e354689be158a.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:33] "GET /profile.fda2296cc373e01300dce68bdaf0991b.jpeg HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:33] "GET /terminal-vim.9b342a7c8be670e9a96e8813c43d8edf.js HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:33] "GET /style.342793b0a19255e7ce615729a45053fe.css HTTP/1.1" 200 -
[WebServer] 127.0.0.1 - - [22/Oct/2026 22:27:33] "GET /script.5596b80e3eb6d4ebf507689493b9c66a.js HTTP/1.1" 200 -
✓ 45 [chromium] › tests/e2e/05-menu.spec.js:30:5 › Navigation menu › clicking outside closes an open mobile menu (569ms)
45 passed (30.7s)
To open last HTML report run:

 npx playwright show-report

+75 -12
View File
@@ -1,6 +1,7 @@
# Developer Homepage
A static portfolio site packaged for deployment with Podman quadlets.
A static portfolio site (vanilla HTML/CSS/JS + a fake terminal easter egg)
packaged as an nginx container and deployed with Podman Quadlet.
## Build & Run with Podman
@@ -12,34 +13,96 @@ podman build -t homepage:latest .
### Run the container
The image runs `build.sh` itself and copies the hashed `dist/` output into the
nginx html root, so the built site is already inside the image:
```bash
podman run --rm -p 0.0.0.0:8080:8080 -v ./src:/usr/share/nginx/html:z homepage:latest
podman run --rm -p 0.0.0.0:8080:8080 homepage:latest
```
To iterate on `src/` without rebuilding the image, build locally and bind-mount
the **built** output over the html root — mount `dist/`, never `src/`, because
`index.html` requests content-hashed filenames:
```bash
./build.sh
podman run --rm -p 0.0.0.0:8080:8080 -v ./dist:/usr/share/nginx/html:z homepage:latest
```
Visit `http://localhost:8080` in your browser.
## Serving & configuration
`nginx.conf` is copied into the image as the site config. It listens on
**8080 over plain HTTP**, serves the hashed build, declares the hardening
headers (`X-Frame-Options`, `X-Content-Type-Options`, `Referrer-Policy`,
`Content-Security-Policy`), serves `index.html` with `no-cache`, and caches the
hashed assets as `immutable` for a year.
Known gap (audit finding M-4, Phase 03): nginx does not merge `add_header`
across configuration levels, so the `location` blocks that set their own headers
drop the server-level security headers — measured against the built image, `/`,
`/index.html` and a hashed asset currently get only the cache headers. Every
`add_header` block must repeat the hardening headers until that phase lands.
TLS and HSTS are the job of the reverse proxy in front of the container
(`reeseapps.com` terminates at the Caddy edge). Do **not** add
`Strict-Transport-Security` or a `listen 443` block to `nginx.conf`.
## Deploy with Quadlet
1. Copy the container definition to systemd:
The `homepage.container` Quadlet unit is **not** tracked in this repository — it
lives with the deployment host's config. Install it under
`~/.config/containers/systemd/` (copy it from wherever the host's unit files are
kept):
```bash
mkdir -p ~/.config/containers/systemd
cp homepage.container ~/.config/containers/systemd/
cp <deploy-config>/homepage.container ~/.config/containers/systemd/
```
2. Reload systemd and start the service:
It must publish host port 8080 and use the image CI publishes:
`gitea.reeseapps.com/services/homepage` (`main` on every push to `main`, plus
one tag per release).
Quadlet is a systemd generator: it turns `homepage.container` into a
`homepage.service` unit when systemd regenerates units, so manage it under the
`.service` name:
```bash
systemctl --user daemon-reload
systemctl --user start homepage.container
systemctl --user start homepage.service
systemctl --user status homepage.service
```
3. Enable auto-start on boot:
```bash
systemctl --user enable homepage.container
```
Auto-start on boot comes from the unit's `[Install]` section (e.g.
`WantedBy=default.target`), which the generator applies while generating — the
Quadlet services are transient, so `systemctl enable` has no effect on them;
re-run `systemctl --user daemon-reload` after editing the unit. For a user-mode
unit that must come up without a login session, enable lingering once:
`loginctl enable-linger $USER`.
## Development
Source files are in the `src/` directory. Edit `index.html`, `style.css`, and `script.js` directly. Rebuild the image after making changes.
Source files live in `src/`: `index.html`, `style.css`, `script.js` and the
flat terminal modules (`terminal.js`, `terminal-commands.js`,
`terminal-vim.js`, `terminal-achievements.js`). Keep every `.js` file flat in
`src/` — `build.sh` only hashes root-level files.
```bash
npm install # installs the pinned @playwright/test dev dependency
./build.sh # src/ -> dist/ (content-hashed asset names)
npm test # Playwright E2E suite against dist/ on 127.0.0.1:8123
```
Always build before testing: the suite exercises the built artifact in `dist/`,
never `src/`. `npm test` starts (or reuses) its own static server, so no manual
server is needed. Rebuild the image (`podman build`) after changing `src/`.
Requires Node.js 20+ (the `@playwright/test` engine floor) and the Chromium
revision cached for the pinned Playwright version — run
`npx playwright install chromium` if it is missing, and see `AGENTS.md` before
bumping the pin.
The validation gate the phased pipeline runs per task is `.agents/validate.sh`
(full E2E suite plus repo-hygiene checks): `bash .agents/validate.sh`.
+5 -15
View File
@@ -117,11 +117,9 @@ function createTerminal(face) {
if (historyIndex < commandHistory.length - 1) {
historyIndex++;
const cmdLine = commandHistory[historyIndex];
const lastLine = content.lastElementChild;
lastLine.innerHTML = '<span class="terminal-prompt">$</span> ' + cmdLine + ' ';
const newCursor = document.createElement('span');
newCursor.className = 'terminal-cursor';
lastLine.appendChild(newCursor);
// Safe display path: recalled history is untrusted input, so it
// renders as text — audit finding M-1.
updateDisplay(cmdLine);
}
return;
}
@@ -131,18 +129,10 @@ function createTerminal(face) {
if (historyIndex > 0) {
historyIndex--;
const cmdLine = commandHistory[historyIndex];
const lastLine = content.lastElementChild;
lastLine.innerHTML = '<span class="terminal-prompt">$</span> ' + cmdLine + ' ';
const newCursor = document.createElement('span');
newCursor.className = 'terminal-cursor';
lastLine.appendChild(newCursor);
updateDisplay(cmdLine);
} else {
historyIndex = -1;
const lastLine = content.lastElementChild;
lastLine.innerHTML = '<span class="terminal-prompt">$</span> ';
const newCursor = document.createElement('span');
newCursor.className = 'terminal-cursor';
lastLine.appendChild(newCursor);
updateDisplay('');
}
return;
}
+42
View File
@@ -150,6 +150,48 @@ test.describe('Fake terminal — state and special commands', () => {
await expect(terminalLines(page).nth(-2)).toHaveText('homelab');
});
// Regression guard for audit finding M-1: history recall rebuilt the prompt
// line with innerHTML, so a markup payload came back to life as DOM on
// ArrowUp. Recall must stay on the textContent path.
test('history recall renders markup payloads as literal text (no DOM injection)', async ({ page }) => {
// Prompt text minus the leading '$ '/'# ' and the trailing cursor.
const typed = async () =>
(await currentPromptLine(page).textContent()).replace(/^[#$] /, '').trim();
// 1) A payload that would create a DOM node if innerHTML-injected.
await typeCommand(page, '<b id="xss-marker">pwned</b>');
await page.keyboard.press('ArrowUp');
await expect(page.locator('#xss-marker')).toHaveCount(0);
await expect(page.locator('.terminal-content b')).toHaveCount(0);
expect(await typed()).toBe('<b id="xss-marker">pwned</b>');
// 2) An event-handler payload must not execute. `data:,` is an empty
// data URI so the <img> fails to decode deterministically (no
// network dependency) and onerror would fire if injected as HTML.
// ArrowDown first returns to an empty prompt (historyIndex -1).
await page.evaluate(() => { window.__xssFired = false; });
await page.keyboard.press('ArrowDown');
expect(await typed()).toBe('');
await typeCommand(page, '<img src="data:," onerror="window.__xssFired=true">');
await page.keyboard.press('ArrowUp');
await page.waitForTimeout(200); // allow onerror to fire if vulnerable
expect(await page.evaluate(() => window.__xssFired)).toBe(false);
await expect(page.locator('img[onerror]')).toHaveCount(0);
expect(await typed()).toBe('<img src="data:," onerror="window.__xssFired=true">');
// 3) Benign recall + execute still works after the payloads: back to an
// empty prompt, type a real command, run it, recall it, run it again.
await page.keyboard.press('ArrowDown');
expect(await typed()).toBe('');
await typeCommand(page, 'whoami');
await expect(terminalLines(page).nth(-2)).toHaveText('reese');
await page.keyboard.press('ArrowUp');
expect(await typed()).toBe('whoami');
await page.keyboard.press('Enter');
await expect(terminalLines(page).nth(-2)).toHaveText('reese');
await expect(page.locator('#xss-marker')).toHaveCount(0);
});
test('Tab completes a command', async ({ page }) => {
await page.keyboard.type('host');
await page.keyboard.press('Tab');