feat: subscriptions management + project name display fix#218
Conversation
|
The new subscriptions + display-project work in this PR looks great ( git fetch origin
git rebase origin/main
# expect conflicts in: ci.yml (just delete your '-2' hunk), src/repo-refresh.js (keep main's timer-tracking)
git push --force-with-leaseWill re-review immediately after. Should be quick. 🙏 |
d831a2a to
1af6aa9
Compare
|
Rebased onto current |
|
Sorry @NovakPAai — same issue again, second order this time. Just merged #216 and the diff for this PR against current Both PRs were rebased onto the same base (pre-#216), so the second one always carries an inverse of the first. One more rebase will fix it: git fetch origin
git rebase origin/main
# expect conflicts in: src/frontend/app.js, index.html, styles.css (#216 touched the same files for sidebar groups; keep both changes)
git push --force-with-leaseThe subscriptions code itself looks ready — |
…splay
Analytics → History tab now lets you track paid subscriptions and API
deposits across all supported services. Service select expanded from
5 to 9 entries (+ API custom): Claude Code, ChatGPT/Codex, Cursor,
Copilot, Kiro, OpenCode, Qwen Code, Kilo, API (custom). Picking a
service populates the Plan select with current pricing (verified
2026-05-15 against vendor pages); picking a plan auto-fills the
monthly amount. API (custom) replaces the Plan select with a free-text
provider/balance input.
Cost by Project and Most Expensive Sessions now show clean project
basenames ("codbash" instead of "~/code/codbash"). Sessions whose path
equals \$HOME group into a single "(home)" row.
Implementation
- Backend helper displayProject() in src/data.js — basename / (home) /
unknown — used in byProject aggregation. 14 unit tests via node:test.
- SERVICE_PLANS extended; kind field discriminates subscription / api /
api-only (Qwen, Kilo).
- Native <select> for Service and Plan (replaces datalist); free-text
input swapped in for API (custom).
- localStorage migration is read-time only, immutable copy; legacy
single-entry format gets a "(legacy) " plan prefix.
- Form is a <form onsubmit> so Enter submits from any field;
updateAddButtonState announces validation reason via aria-describedby.
- Subgroups (Subscriptions / API deposits) use <h4> headings.
- Touch target on Remove × bumped to 32×32 (WCAG 2.5.8 AA).
- Responsive @media flips form to single column under 480px.
- Three-agent review (code / security / UX-with-skills): all CRITICAL,
HIGH, MEDIUM addressed; selected LOW deferred with reasons in PR body.
1af6aa9 to
2cc0ff2
Compare
|
Rebased on current |
Summary
API (custom): Claude Code · ChatGPT/Codex · Cursor · Copilot · Kiro · OpenCode · Qwen Code · Kilo · API (custom). Pick service → Plan select populates; pick plan → monthly amount auto-fills. Prices verified 2026-05-15 against vendor pages.codbash(basename) instead of~/code/codbashor$HOMEprefix. Sessions whose path equals$HOMEmerge into a single(home)group.What's changed
Backend (
src/data.js):displayProject(session)helper — basename /(home)/unknown. Used inbyProjectaggregation. Exported via__test.test/display-project.test.js(node:test, zero-dep).Frontend:
SERVICE_PLANSextended withkindfield (subscription/api/api-only).renderPlanSlot(cfg)swaps a native<select>for Plan into a free-text<input>when service isAPI (custom).<form onsubmit>— Enter submits from any field.updateAddButtonStateannounces validation reason viaaria-describedby="sub-new-hint".<h4>headings + subtotals.(legacy)plan prefix.#sub-aria-liveupdated beforerender()for add/remove announcements.@media (max-width: 480px)— form collapses to single column.Quality gates
node --checkon all touched filesnode --test test/display-project.test.jsnode --test test/*.test.jsvercel-web-design-guidelines+ux-designerskills)tasks/2026-05-15-analytics-subscriptions/smoke-report.md)Deferred (with explicit reasons)
#sub-aria-liveas body-level singleton — currently announced beforerender()and works in Chrome/Safari. Promoting the live region to a<body>-level singleton that survivesrender()is an app-wide refactor — follow-up PR.s.id/s.dateunescaped inanalytics.js(Most Expensive Sessions row) — pre-existing code on lines 338, 341 outside this diff. Tech debt, separate task.requiredon selects — manual validation inupdateAddButtonStatealready gates submission; nativerequiredwould override the custom logic.from='',role=list/role=listitemon rows) — none break the BDD acceptance scenarios; queued for next a11y polish pass.var(--text)references instyles.css(lines 1850, 1878, 3053, 3155) — outside this diff. Should be replaced withvar(--text-primary)in a CSS cleanup PR.Test plan
git checkout feat/analytics-subscriptions && node bin/cli.js run --port 8765 --no-openhttp://localhost:8765, switch to Analytics → History.Claude Code→ Plan options appear → pickMax 5×→ Paid auto-fills100.API (custom)→ Plan field becomes free-text input with placeholderProvider / balance label; Paid placeholder changes to$ deposit.Qwen Code→ hint readsFree / API-only — use "API (custom)" to track deposits; Add disabled.codbash,flow-tasks,(home), etc.) — no~/, no$HOME.{plan, paid}migrates to(legacy) <plan>without errors.Artifacts
docs/design/analytics-subscriptions.mdspecs/analytics-subscriptions.feature(6 categories: happy / empty / loading / error / keyboard / edge-data)tasks/2026-05-15-analytics-subscriptions/plan.mdtasks/2026-05-15-analytics-subscriptions/smoke-report.md