Flip parked-work.md + CLAUDE.md from "paused, not pushed" to "pushed to origin/ai-dev d7015b9..4c25011, Flatlogic VM deploy pending (migrate + collectstatic + restart-last)". Prevents a fresh session reading stale "not pushed" status. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
16 KiB
Parked / deferred work
Updated 15 May 2026. A small index of features that are designed, half-built, blocked on input, or pending an operator step. When a fresh session opens, glance here first to see what's already on the workbench.
⏸ Paused — ready to execute (not started, not pushed)
Post-Attendance Flow v2
Status: Brainstormed + designed + planned, approved by Konrad,
execution paused (Konrad's call, 15 May 2026). Design doc
docs/plans/2026-05-15-post-attendance-flow-v2-design.md (local
commit 110545b), plan docs/plans/2026-05-15-post-attendance-flow-v2-plan.md
(local commit 29c36be). These 2 commits are local-only on
ai-dev, NOT pushed to origin — Konrad wants nothing reaching the
working app until he's verified the flow locally.
What it does: Replaces the forced post-attendance SiteReport redirect with 3 explicit buttons (Log Work → dashboard / + Site Journal / + Absences) + a "Save Site Journal + Add Absences" button on the journal page. Renames user-facing "Site Report" → "Site Journal" (display-only, Path-A — frees "Journal" for the parked voice feature, which must now be called "Voice Notes").
To resume: new or same session → "execute the
post-attendance-flow-v2 plan". 4 tiny TDD tasks (~120 LOC), reuses
the proven Round C next_action pattern. HARD STOP after Task 4
— Konrad runs the manual verification checklist (in the design doc)
locally and explicitly approves BEFORE any push. No migrations /
collectstatic — pure template + view change.
🚀 Pushed to origin/ai-dev — pending Flatlogic deploy + prod verification
Manager / Salaried Pay (+ pay-type filter + Salary auto-scope + Pay Salary quick action)
Status: Brainstormed + designed + planned + fully
implemented, every task two-stage code-reviewed. PUSHED to
origin/ai-dev on 16 May 2026 on Konrad's explicit "push" go-ahead
— the full 36-commit bundle d7015b9..4c25011 (origin/ai-dev
HEAD is now 4c25011). This is the original Manager/Salaried feature
(Tasks 1-7) PLUS three stacked refinements built + reviewed the same
day: the display-only pay-type filter, the Salary auto-scope picker,
and the Pay Salary dashboard quick action. 209/209 tests green
locally. Design/plan docs: 2026-05-15-manager-salaried-pay-*,
2026-05-16-managers-paytype-filter-*,
2026-05-16-salary-autoscope-picker-*,
2026-05-16-pay-salary-quick-action-* (all under docs/plans/).
⚠ NOT yet deployed to production. The push reached
origin/ai-dev (GitHub) only. The Flatlogic VM still needs the
ordered deploy (DEBUG=False template-cache rule applies):
(1) git fetch github ai-dev && git reset --hard github/ai-dev,
(2) git push gitea ai-dev, (3) python3 manage.py migrate
(applies 0016_worker_pay_type + 0017_alter_payrolladjustment_type),
(4) python3 manage.py collectstatic --noinput (static/css/custom.css
changed — --badge-salary-*), (5) sudo systemctl restart django-dev.service LAST, (6) confirm git log shows 4c25011
then restart again if the restart preceded the pull.
What it does: Lets a manager / salaried worker be paid a fixed
monthly amount without ever logging attendance. A new
Worker.pay_type ('daily' default | 'fixed') marks managers;
they're excluded from attendance + absence pickers ONLY (NOT payroll
modals / TeamForm — they must stay payable), and paid via a new
Salary PayrollAdjustment type (project-required; "Pay
Immediately" → isolated PayrollRecord like New Loan; unpaid nets via
_process_single_payment). The report shows a separate per-project
"Management / Salaried Cost" line — never merged into WorkLog-derived
daily labour cost, so all existing money math is provably unchanged.
"Manager / Salaried" is a Path-A display-only label (model stays
Worker). Migrations 0016_worker_pay_type, 0017_alter_payrolladjustment_type.
To resume: the push is done; the remaining step is the Flatlogic
VM deploy (ordered steps in the Status block above — migrate +
collectstatic + restart-last). After Gemini/Konrad deploys, verify on
https://foxlog.flatlogic.app/ using the manual checklists in the four
design docs, then update this file's "Production status" + the CLAUDE.md
"What's mid-flight" breadcrumb to "fully caught up at 4c25011". No
code changes pending — implementation is complete and reviewed.
Now also includes a display-only pay-type filter (design
docs/plans/2026-05-16-managers-paytype-filter-design.md, plan
docs/plans/2026-05-16-managers-paytype-filter-plan.md): a
/workers/?pay_type=fixed filter + dropdown and a "Managers only"
client-side toggle on the Add-Adjustment modal picker. Shipped in
the 36-commit push d7015b9..4c25011.
Also now: setting the Add-Adjustment type = Salary auto-scopes
the picker — pay-type filter → "Managers only", daily rows hidden,
and any selected daily worker auto-unticked (UI guard so a Salary
can never silently target a daily worker). Design
docs/plans/2026-05-16-salary-autoscope-picker-design.md, plan
docs/plans/2026-05-16-salary-autoscope-picker-plan.md. Shipped in
the 36-commit push d7015b9..4c25011.
Also now: a home-dashboard admin Quick Actions tile "Pay Salary"
deep-links /payroll/?action=pay-salary and auto-opens the existing
Pay Salary modal (param stripped after; no re-pop on refresh). Design
docs/plans/2026-05-16-pay-salary-quick-action-design.md, plan
docs/plans/2026-05-16-pay-salary-quick-action-plan.md. Shipped in
the 36-commit push d7015b9..4c25011.
Follow-ups from code review (parked, out of scope for this feature)
- Atomicity hardening (cross-cutting, pre-existing).
add_adjustment's three immediate-payment branches —New Loan,Advance Payment, and nowSalary— create aPayrollAdjustmentPayrollRecordand call_send_payslip_emailWITHOUT a wrappingtransaction.atomic(), and_send_payslip_emailre-raises on email failure. A mid-sequence failure can therefore orphan a payment row / 500 after commit. This is PRE-EXISTING (Salary just consistently matches the New Loan / Advance pattern, it did not introduce the gap) — flagged by Task 5 code review as a separate hardening ticket, NOT a Manager/Salaried defect. Recommended future cross-cutting fix: wrap each immediate-branch body intransaction.atomic()and swallow/log email failures the wayprocess_paymentalready does. Out of scope for this feature.
- Pre-existing flaky test.
AbsenceListViewTests(incore/tests.py) has anassertContains/assertNotContainsagainst the/absences/list HTML that intermittently failed ~1-in-3 in one run during this feature's execution, then passed on rerun; 3+ subsequent full-suite runs were clean. A reviewer's isolation analysis concluded it's pre-existing environmental nondeterminism (proper DjangoTestCasetransactional isolation; the Manager/Salaried tests cannot perturb it). Low priority: investigate a possible date/locale or response-rendering nondeterminism in that test. NOT introduced by this feature.
Note: the Post-Attendance Flow v2 paused entry above is STILL paused / unchanged — this Manager/Salaried entry does not affect it.
Production status — ✅ fully caught up (15 May 2026)
Production (https://foxlog.flatlogic.app/) is deployed at
origin/ai-dev HEAD 1d224bc. Everything is live: SiteReport
- Absences feature, all UX polish, the team filters, the dashboard/report number audit (18 findings), and the template-comment + subline-clarity fixes.
Deploy-ordering lesson learned (now in CLAUDE.md): production
runs DEBUG=False → Django's cached template loader holds compiled
templates in memory until the process restarts. The 14 commits of
template fixes were briefly "invisible" because the service was
restarted before the code reached the target commit. The fix was
simply to restart AGAIN once git log confirmed the right commit.
Correct order is always: git reset --hard github/ai-dev → migrate
(if needed) → collectstatic (if static/ changed) → restart
last. See the "DEPLOY ORDERING" bullet in CLAUDE.md's
Flatlogic Deployment section.
🧊 Backburner — journal/voice features (separate offline track)
Decision (15 May 2026): Konrad parked the entire journal / voice-transcript line of work. It's more complex than the rest of the app and will be built + tested offline, on a separate track, NOT mixed into
ai-dev. Do NOT start either of these inai-devor in any normal feature session. They are not "blocked waiting on an answer" — they are deliberately deferred until Konrad chooses to spin up a dedicated offline effort.
Important — nothing is in the working app. Verified 15 May 2026:
zero JournalEntry model / views / URLs / templates anywhere in
core/, zero Letterly / webhook / @csrf_exempt code on ai-dev,
latest migration is 0015_absence_project. There is no dead code,
no feature flag, no migration to reverse. "Removing" these was a
no-op — they were never built into the running app. The working
app (ai-dev + production) is completely clean of journal/voice
code.
Phase A.2 — Manual JournalEntry web UI (deferred)
Designed in the Site Work Logging brainstorm (~/.claude/plans/ prancy-painting-brook.md, local). A JournalEntry model + manual
entry form/list/edit, admin-only. Open question if/when resumed:
Q7 "Who is Vi?" — drives whether JournalEntry needs a
recipient/audience field. Default if never answered: no
recipient field, all-admin-readable. ~1 hour scope. When resumed,
build on the offline track first, not directly in ai-dev.
Phase B — Letterly inbound webhook (deferred)
Designed in the same brainstorm. A @csrf_exempt view at
/webhooks/letterly/ that creates JournalEntry rows from voice
transcripts, with HMAC body verification + shared-secret URL token.
Open question if/when resumed: Q5 — a sample Letterly webhook
payload (does it include the recording user / project metadata /
audio URL / custom fields?). ~3-4 hours scope + one-off Letterly
account setup. This was always meant to live on the integrations
branch, never ai-dev — and now it's offline-track until Konrad
revisits.
Small polish follow-ups from the Absences feature
All 7 cleared on 15 May 2026 (commit
d1d3e15). Kept the section header in place because more polish items will accumulate from future code reviews — when they do, append here. The shipped items are summarized under "Recently shipped" below.
Defaulted (not blocking — flag if you disagree)
From Q9, Q4 of the Site Work Logging brainstorm:
- Q9 — photos on site reports. Deferred to v2 of SiteReport. Construction supervisors often want to attach a phone photo of "plinths cast today" but it adds ~50 LOC + storage handling + thumbnail rendering. v1 ships without.
- Q4 — per-project metric templates. Same metric set for all
projects in v1. If/when a non-solar-farm project lands and the
metrics diverge wildly, we add a
MetricTemplatemodel. YAGNI for now —core/site_report_schema.pyis one Python file edit.
Recently shipped (for context, so a fresh session knows what just landed)
- Dashboard + report numbers audit (commits
18c75b2→c02edce, 15 May 2026): Konrad spotted that the home dashboard's "Paid This Month" actually showed the last 60 days. A thorough audit found 17 more issues across the home dashboard, payroll dashboard, and report. All 18 fixed in 7 commits: calendar-month math, outstanding totals aligned between dashboards,Project.namededupe (was silently merging same-named projects),timezone.localdate()replacingtimezone.now().date()(SAST drift fix), off-by-one on "last 7 / 60 days" windows, deadyear_projects/year_teamscontext removed,_company_cost_velocityrewritten as single SQL aggregate, signed/coloured adjustment amounts on report tables (Bonus vs Deduction now visually distinct), "Outstanding Now" hero card subline now shows scope when filters active, dual daily_rate code paths documented in CLAUDE.md. 160 → 173 tests (+13 regression). - Absence-feature polish pass (commit
d1d3e15, 15 May 2026): Seven small cleanups in one focused commit. (1) Deleted unusedAbsenceQuickForm(Round C made it obsolete). (2) Extracted_build_team_workers_map(user)helper usingPrefetch(..., to_attr=...), fixing N+1 on bothattendance_logandabsence_log(one query instead of one-per-team). (3)absence_listnow calls the existing_user_can_log_absenceshelper. (4) Removed undefinedvar(--badge-neutral-bg)CSS wrapper — fallback hex was always winning anyway. (5)conflicting_worklogs()rewritten as a single query with Python-side pair-set filtering — 25-query → 2-query for a 5×5 form. (6) Extracted_apply_absence_filters(qs, request)shared byabsence_list+absence_export_csvso adding a filter param now touches one place, not two. (7)site_report_detail.htmlpaid-check icon usestext-successinstead of background-color variable as foreground (WCAG contrast fix). 157/157 tests still green. - Day name in Work Log Payroll modal header (commit
70fa085, 15 May 2026): The modal opened from /history/ now shows "Friday, 15 May 2026" instead of "2026-05-15". Pure server-sidestrftimeon the already-loadedlog.date— zero overhead. - Team filters on
/workers/and/history/(commits4b57cff,398a5b2, 15 May 2026): Both pages now have a Team dropdown in their filter row./workers/?team=<id>filters by Team.workers M2M membership (who's CURRENTLY on the team);/history/?team=<id>filters by WorkLog.team FK (logs TAGGED with the team when created — different semantics, intentional). Both acceptteam=nonefor the "no team assigned" / "ad-hoc work log" case. CSV export at/history/export/honours the same param. +8 regression tests. - Absences UX polish (commits
4368e53,02c6d4d, 15 May 2026): Two production-found bugs fixed. (1) Absence-form team filter was hiding ALL workers when a team was selected — switched the JS to read<input name="workers">[value]directly instead of going throughdata-worker-id(proven attendance-form pattern). (2) Reasons multi-checkbox dropdown on/absences/was rendering behind the table — lifted the filter card withposition: relative; z-index: 10so the whole card sits above its sibling table card in the stacking order. See the Coding Style section in CLAUDE.md for both gotchas. - Worker Absences feature (commits
bf6f0a5→27fe05e, 14 May 2026): Complete absence-tracking system. 8 reason choices, optional project FK (auto-attributes paid-absence Bonus adjustments to the project), date-range logging with weekend toggles, supervisor scoping (admin sees all; supervisors see their teams). Standalone/absences/log/form + "Submit + Log Absences" shortcut on attendance form. List/edit/delete + CSV export. Worker-detail "Absences" tab with YTD totals. Dashboard alert card "X absent in last 7 days". Bidirectional cascade with PayrollAdjustment via_sync_absence_payroll_adjustmenthelper (single-chokepoint design, transaction.atomic-wrapped). 12 commits pushed toorigin/ai-dev. Test count: 85 → 149 (+64 tests). Migrations0013_add_site_report,0014_add_absence,0015_absence_projectare LIVE on production as of late 14 May 2026. - Phase A.1 — SiteReport (commit
864ae72, 14 May 2026): Model, migration0013_add_site_report.py, form, two-step flow from attendance log, 16 new tests.CLAUDE.mdupdated with model summary +site_report_schema.pypattern section. - Pastel soft-fill payroll action buttons (commit
6c6ade9, 24 Apr 2026): unified Worker Lookup / Batch Pay / Add Adjustment / Price Overtime treatment. - Path A display-only rename (UX Polish Pass, Apr 2026):
"New Loan" / "Advance Payment" / "Advance Repayment" display as
"Loan" / "Advance" / "Advance Repaid" — but DB values are
unchanged. See "UI-vs-DB naming drift" section in
CLAUDE.mdbefore writing any filter/comparison onPayrollAdjustment.type.
Original Site Work Logging brainstorm
The full Q1-Q13 question list and design rationale lives in
~/.claude/plans/prancy-painting-brook.md (local — deliberately
not committed to the repo, since the parts that matter have been
absorbed into CLAUDE.md and this file). If Konrad answers Q5 or
Q7 later, refer back to that file for the original framing.