Commit graph

210 commits

Author SHA1 Message Date
bce71a666a feat(schema): commit summary fields 2026-09-16 16:15:18 +02:00
2401dbd68f test(ai): settings page never exposes the API key
Three tests cover the storage and access boundary:

- A client manager cannot list the settings collection at all (rules are
  superuser-only — verified by the rejection, not by silent skip).
- The settings page HTML returned to the owner does not contain the key
  value, even when the key is freshly set to a unique sentinel.
- A client manager gets 404 on /admin/settings (admin layout gates on
  role, not on session presence).

helpers.ts gained ownerEmail / ownerPassword — needed by the settings test
and reusable for any owner-only integration test going forward.
2026-09-16 15:59:49 +02:00
70cb355762 feat(ai): settings page with a real connection test 2026-09-16 15:54:58 +02:00
e837500c6f feat(ai): single point of provider selection 2026-09-16 15:53:59 +02:00
b233259f18 feat(ai): OpenAI-compatible adapter for MiniMax 2026-09-16 15:53:34 +02:00
b172079912 feat(ai): Anthropic adapter 2026-09-16 15:52:56 +02:00
79fa035eb0 docs(plan): Phase 3a, 3b and 3c for AI humanisation
3a ports the provider structure from MEGAIFRASTRUCTURE's chat/ — SDK-free
types, one adapter per provider — but deliberately not its interface: this
phase needs text in, text out, not a chat transcript and tool protocol. It
carries forward the MiniMax details that module learned the hard way: the
native /v1 route rather than the /anthropic shim, an Open Platform key, and
stripping the inline <think> blocks M2.x emits.

3b is built around one property: batch responses are matched to commits by
an echoed index, never by position. A single skipped line under positional
matching would attach fluent, confident, wrong sentences to every later
commit, with nothing raising an error.

3c is the first plan whose output a client reads, so its verification step
is to read a narrative as the client would and check it claims no
completion, states no date, and invents nothing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-16 15:52:32 +02:00
f3e4b30d46 feat(ai): settings storage with a browser-safe projection 2026-09-16 15:52:12 +02:00
8f1ac43e98 feat(ai): strip MiniMax inline reasoning blocks 2026-09-16 15:51:37 +02:00
b5593457af feat(ai): non-editable preamble with an append-only owner prompt 2026-09-16 15:51:15 +02:00
44bcc81d97 feat(ai): provider-neutral completion interface 2026-09-16 15:50:39 +02:00
76be7440a8 feat(dashboard): remove the 'estimated' pill from the Hours KPI
The methodology panel already explains that hours are estimated from
commit timing — the pill on the tile was redundant. With the pill gone
the tile row reads as four plain figures, and the methodology is the
single place a client goes to interrogate any of them.
2026-09-16 15:38:42 +02:00
6c391e04a3 fix(dashboard): month bars render with definite-height parent
The chart column was flex-1 inside h-40, but had no explicit height of
its own. The bar inside used height: X% which has nothing to compute
against when the parent is auto-sized — Tailwind's percent utilities
collapse to 0 without a definite parent.

Wrap the bar in a flex-1 container that consumes the remaining vertical
space. The percentage now resolves against that container's actual height,
so the 154h August bar fills three-quarters of the way up the column,
the 5h May bar barely peeks above the baseline, and the rest sit between.
2026-09-16 15:36:50 +02:00
c531abda45 docs(spec): Phase 3 design for AI humanisation of commit history
One-liners per commit and a progress narrative per card, plus the
swappable provider layer both depend on, ported from the chat/ structure
in MEGAIFRASTRUCTURE.

Model and cost are measured rather than assumed: the full 779-commit
backfill costs about ninety cents on claude-opus-5, so model choice here
is a quality decision and not a cost one. Batch API considered and
rejected — it saves roughly forty cents and adds a job state machine.

Records the rules the non-editable preamble must guarantee, each tied to
a specific way a summary could mislead a paying client.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-16 15:36:28 +02:00
9d413c5976 feat(dashboard): change 'estimated' pill to brand tone
The neutral (gray) pill read as a status badge rather than an integral
annotation. The brand tone ties the indicator visually to the brand,
making it part of the figure rather than an overlay. The meaning is the
same — 'this number is not measured, it is computed' — and the methodology
panel still explains exactly how.
2026-09-16 15:35:41 +02:00
7361dd848f feat(dashboard): trim methodology first sentence further
The 'Hours here are estimated' phrasing was redundant with the 'estimated'
pill on the Hours KPI tile — the pill is the visual signal, the methodology
doesn't need to repeat it. Left is just 'Git records what changed and when,
but not how long it took.' which sets up the next paragraph.
2026-09-16 15:31:16 +02:00
19e9dc29ac feat(dashboard): remove session-clustering paragraph from methodology
The methodology panel still explains 'what hours are' and 'what they cannot
see'. The session-clustering detail — the constants — was the part a client
might want to interrogate rather than just be told. With this removed, the
constants are still stored inside the payload (so a future question can be
answered) but the visible panel is shorter.

Also dropped the now-unused destructured local in Methodology().
2026-09-16 15:30:46 +02:00
cd0984595c test(metrics): cached figures agree with stored commits + vitest stubs
The integration project now aliases server-only to a tiny empty stub
so tests can import modules that carry 'import "server-only"' without
the throwing real implementation firing during prepare. Unit tests do
NOT get the alias — a pure module with a server import is exactly the
kind of leak the unit project's missing condition is meant to surface.
2026-09-16 15:19:32 +02:00
53979f389d feat(dashboard): project dashboard page 2026-09-16 13:52:13 +02:00
2792f4ea93 feat(dashboard): KPI row and always-visible methodology panel 2026-09-16 13:51:34 +02:00
be49a69b2f feat(dashboard): SVG activity calendar and bar charts 2026-09-16 13:51:18 +02:00
cc20cf4bfd feat(metrics): cached project metrics recomputed on ingest 2026-09-16 13:51:03 +02:00
dbf524b04c feat(metrics): activity calendar grid 2026-09-16 13:46:26 +02:00
b379669db3 feat(metrics): project metric aggregation from commits 2026-09-16 13:45:56 +02:00
b4d4a3bcb6 feat(metrics): session clustering with defined boundaries
The plan's summariseSessions test expected 2 sessions for four commits
spanning two 3-hour gaps, but with the default 120-minute gap three hours
is too far and produces 3 sessions. The implementation matches the boundary
rule defined in the plan (strictly less than the gap continues a session);
the test was off. Adjusted to a 90-minute follow-up which keeps the same
session and verifies total + longest correctly.
2026-09-16 13:45:01 +02:00
265d623220 feat(metrics): SA public holidays and workday counting 2026-09-16 13:44:01 +02:00
a1ef2ff55c chore(relink): CLI helper for off-server relink runs 2026-09-16 13:36:42 +02:00
7fc87042f6 test(linking): idempotency, manual precedence and date bounding
Vitest config: integration project now resolves with the 'react-server'
condition, so server-only modules can be imported directly from tests.
The unit project deliberately does NOT set it: a unit test pulling in a
server-only module must fail loudly, because a pure module with a server
import is exactly the kind of leak that should not reach production.
2026-09-16 13:34:53 +02:00
444612fc55 feat(linking): unassigned commit tray with manual attachment 2026-09-16 13:24:57 +02:00
d7e0b97ff4 feat(linking): re-link on ingest and on card rule changes
- ingestProject now calls relinkProject after every store
- updateCard relinks when scopeScope rule is in the patch
- acceptCard, archiveCard, unlinkCommitArchiveCard relink after their change
- three owner Server Actions for the tray: relinkProjectAction, linkCommitAction, unlinkCommitAction
2026-09-16 13:24:17 +02:00
25b504c901 feat(linking): idempotent relink engine preserving manual links 2026-09-16 13:23:33 +02:00
9c27d34c3e feat(linking): commit-to-card resolution with date bounding 2026-09-16 13:21:26 +02:00
7970edf7c2 feat(linking): explicit [#42] card references 2026-09-16 13:20:56 +02:00
d06d1e99ec feat(cards): per-project card numbers for commit references
- number field on cards, unique per project
- backfilled existing cards in created order
- both create paths (owner action, client API) assign on creation
- seed script is idempotent across re-runs
2026-09-16 13:20:24 +02:00
0fd2cef2cf docs(plan): Phase 2b and 2c for commit linking, metrics and the dashboard
2b closes a gap between the spec and the schema: the spec's [#42] explicit
link had nothing to reference, because cards only had PocketBase ids. Adds
per-project card numbers, and sharpens two rules the spec left loose — a
scope rule is bounded by start_date OR created, and ties go to the card
with the latest bound rather than the most recently edited one.

2c builds the dashboard. The South African holiday table is verified
against the Hermes build log: 24 May to 8 Sep 2026 gives 108 calendar days
and 75 workdays, both exact, and that is now a regression test.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-16 12:52:42 +02:00
9289bf3511 chore(backfill): CLI helper for off-server backfill runs 2026-09-16 11:54:37 +02:00
cd9c8df031 test(ingest): webhook and cron endpoint protection 2026-09-16 11:50:20 +02:00
8c60c1dc1b feat(admin): repository linking, webhook setup and backfill 2026-09-16 11:49:31 +02:00
0236a0b1eb feat(actions): backfill and webhook secret rotation 2026-09-16 11:49:02 +02:00
c5246f66f3 feat(api): hourly reconciliation endpoint 2026-09-16 11:48:41 +02:00
e8cd596702 feat(api): signature-verified Forgejo webhook endpoint 2026-09-16 11:48:20 +02:00
198a7a8ceb feat(git): shared idempotent ingest core 2026-09-16 11:47:55 +02:00
809983ee5c feat(git): Forgejo commit API client
Verified against the live instance: status 200, total 787 commits, first
sha 1bc0da40... 'feat(customers): lift active/inactive toggle to top of
customer form'.
2026-09-16 11:47:22 +02:00
a05c1b8ae0 feat(schema): commits collection and project ingest fields 2026-09-16 11:46:57 +02:00
b8cd766c89 feat(git): timing-safe webhook signature verification 2026-09-16 11:45:32 +02:00
ff423fe3ba feat(git): strict conventional-commit parsing 2026-09-16 11:45:15 +02:00
3f9bbb783a docs(plan): Phase 2a implementation plan for commit ingestion
Eleven tasks covering conventional-commit parsing, HMAC webhook
verification, the Forgejo client, a shared idempotent ingest core, the
webhook and reconciliation endpoints, and the backfill admin panel.

The Forgejo API shape, pagination headers and merge counts are measured
against the live instance rather than recalled, and the plan says so, so
the implementer builds against facts.

Surfaces one unresolved issue for decision: projects.webhook_secret is
readable by a client manager straight from PocketBase, because rules are
record-level and cannot hide a field.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-16 11:41:57 +02:00
38d3758d2d feat(brand): align default client brand colour with new teal palette 2026-09-16 11:34:51 +02:00
40af2b4c98 feat(theme): retune tokens to Modern Color Palette
Palette:
  #051a2d Deep Navy    -> page (dark base) + text-primary (light)
  #068187 Teal Green   -> brand (light mode, AA contrast on white)
  #10bbc3 Aqua Blue    -> brand (dark mode, vibrant on navy)
  #fea24f Sunset Orange -> priority-high
  #a60e35 Crimson Red  -> accent + priority-critical

The plan's reservation rules are preserved: the crimson accent still appears
only on overdue dates, the inbox count badge, and critical priority.
2026-09-16 11:34:29 +02:00
ef9487dae9 docs(spec): Phase 2 design for commit ingestion and the project dashboard
Builds on the Hermes build log Dave produced by hand from WFDASH-WEBAPP,
adopting its metric set, activity calendar and workdays-not-calendar-days
framing, and correcting three things: the "6 contributors" who were one
person plus AI agents, two undocumented hour methodologies, and monetary
framing that suited an internal audience but not a client-facing page.

Settles the effort methodology with named constants shown on the page,
excludes merge commits (verified: 787 total, 779 non-merge, 8 merges), and
requires HMAC verification on the webhook endpoint.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-16 11:32:54 +02:00