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