Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
3125d5c
feat: Pipeline Monitor, Lean metrics, Jenkins integration, bulk inges…
Apr 9, 2026
c9b5cf6
feat: replace DevLake with direct source connectors (ADR-005)
alnascimento-webmotors Apr 9, 2026
54d7002
fix: harden connectors — Jira POST search/jql, board filtering, PR en…
Apr 10, 2026
ed69c6a
refactor: remove dead DevLake code and dependencies
Apr 10, 2026
221db7c
test: add 321 unit tests for custom connectors and data pipeline
Apr 10, 2026
7f9f339
feat: batch persistence for PR ingestion — upsert per repo instead of…
Apr 13, 2026
6b3183c
feat: real-time ingestion progress dashboard with batch tracking
Apr 13, 2026
36d9157
feat: emit 'starting' signal per repo for instant UI progress updates
Apr 13, 2026
60fe576
perf: migrate PR fetch to GraphQL + parallelize repos (40x faster)
Apr 13, 2026
6c3c0cd
fix: retry source count after repo cache warms up
Apr 13, 2026
0723df9
fix(jira): discover sprint+story_points custom fields; link PRs to is…
Apr 13, 2026
1f9ac52
feat(jira): add issue_key column to unblock PR↔issue linking
Apr 13, 2026
c243a87
feat(jira): foundation for dynamic project discovery (ADR-014)
Apr 13, 2026
efaeba7
feat(jira): discovery service, mode resolver, guardrails, scheduler (…
Apr 13, 2026
bea8b13
feat(jira-admin): API endpoints + React UI for dynamic discovery (Pha…
Apr 13, 2026
c5350dc
feat(jira): security hardening, PII gating, tests + Phase 4 rollout
Apr 13, 2026
fd33499
feat(jenkins): config-driven job loading, repo name resolution + inge…
Apr 14, 2026
d1aebf7
feat(jenkins): auto-discover 577 PRD jobs via SCM scan across 283 repos
Apr 14, 2026
3e025c5
feat(pipeline-monitor): v1 Pipeline Monitor + Jira Settings integration
Apr 16, 2026
9c6353a
feat(metrics+dashboard): honest DORA numbers, global filters, dual Le…
Apr 17, 2026
3897751
feat(kanban): Flow Health endpoint + capability-aware UI + Kanban met…
Apr 17, 2026
ba262db
feat(flow-health): squad-first UI + issue titles/descriptions/types +…
Apr 18, 2026
ca8f30f
feat(testing): major — E2E test foundation with platform/customer arc…
Apr 20, 2026
f2af986
feat(backfill): 65x speedup on Jira descriptions via bulk JQL search
Apr 20, 2026
0a1050c
feat(ops): FDD-OPS-001 lines 1+2 — eliminate stale-code-in-workers drift
Apr 23, 2026
26f0804
fix(sec): FDD-SEC-001 — reject squad_key with invalid chars (HTTP 422)
Apr 23, 2026
5d71618
feat(ops): FDD-OPS-001 lines 3+4 — snapshot drift monitor + deploy wo…
Apr 23, 2026
022da38
test(frontend): Sprint 1.2 step 1 — Vitest + RTL + MSW + Zod foundation
Apr 23, 2026
dd10d34
docs(backfill): FDD-OPS-002 — full Jira description backfill SHIPPED
Apr 23, 2026
a8cd881
test(frontend): Sprint 1.2 step 2 — Playwright setup + first E2E smoke
Apr 23, 2026
cf85701
test(frontend): Sprint 1.2 step 3 — Zod contracts for 6 metric endpoints
Apr 23, 2026
d2676e8
feat(sec): Sprint 1.2 step 5 — Gitleaks secret scanning (pre-commit)
Apr 23, 2026
451cf8e
test(frontend): Sprint 1.2 step 4 — axe-core a11y gate on 3 critical …
Apr 23, 2026
d62381e
ci: Sprint 1.2 step 6 — root-level GitHub Actions with 4 blocking gates
Apr 23, 2026
b46e037
docs(sec): secret rotation runbook + make targets + AI-chat guard in …
Apr 23, 2026
9b371e0
fix(ci): add missing @vitest/coverage-v8 dep for test:coverage script
Apr 23, 2026
ef1e1cc
fix(ci): ESLint flat config migration + surface 3 real TS bugs CI found
Apr 23, 2026
2de0373
test(frontend): FDD-DSH-070 fechamento — regression tests + coverage …
Apr 24, 2026
64b0a9d
test(frontend): FDD-DSH-033 fechamento — a11y gate on 10 dashboard ro…
Apr 24, 2026
1a3f68e
chore(dx): PR#1 — doctor + verify-dev scripts for dev onboarding
Apr 24, 2026
80f1796
fix(perf): partial index on metrics_snapshots — fixes /metrics/home 5…
Apr 27, 2026
334992e
docs(quality): close the perf/scale gap exposed by 2026-04-24 incident
Apr 27, 2026
b2c31f5
feat(dx): PR#2 — seed_dev.py for deterministic fake data + 5 safety g…
Apr 27, 2026
d7e2b4a
docs(ingestion): discovery-only philosophy + spec catch-up (§2.3, §3.…
Apr 27, 2026
40ca7e4
Revert "feat(dx): PR#2 — seed_dev.py for deterministic fake data + 5 …
Apr 27, 2026
e5020c9
docs(ops): FDD-OPS-012 — issue sync batch-per-project (parity with PRs)
Apr 28, 2026
c5e38bb
docs(architecture): ingestion v2 — diagnostic + 10× target + migratio…
Apr 28, 2026
4d1c9b4
feat(ingestion): Phase 1 of v2 — issues sync streams per-project (FDD…
Apr 28, 2026
62c183f
fix(ingestion): strip NULL bytes (0x00) from text fields before persist
Apr 28, 2026
4c2c1c5
docs(ingestion): Phase 2 drafts — per-source workers + per-scope wate…
Apr 28, 2026
c2c6e5d
feat(ingestion): Phase 2 step 2.1 — apply scope_key migration
Apr 28, 2026
a2d5850
feat(ingestion): Phase 2 step 2.2 — per-scope watermark API
Apr 28, 2026
f357d05
feat(ingestion): Phase 2 step 2.3 — _sync_issues uses per-project wat…
Apr 28, 2026
15574a7
feat(ingestion): Phase 2 steps 2.4 + 2.5 — per-repo watermark writes …
Apr 28, 2026
1516bbf
docs(ingestion): Phase 2 plan — update status to PARTIAL after 2.1-2.…
Apr 28, 2026
4f86fd2
fix(ingestion): Phase 2-B step 2.7 (urgent) — drop legacy uq_watermar…
Apr 28, 2026
4478f13
feat(ingestion): Phase 2-B step 2.4-B — read per-repo watermarks for PRs
Apr 28, 2026
c628528
feat(ingestion): Phase 2-B step 2.5-B — read per-repo watermarks for …
Apr 28, 2026
177830e
fix(ingestion): preserve Jira changelog in _map_issue so inline extra…
Apr 28, 2026
172f3f2
feat(ingestion): effort estimation fallback chain (FDD-OPS-016)
Apr 29, 2026
0c7124d
fix(metrics): status normalization with statusCategory fallback (FDD-…
Apr 29, 2026
649ed78
fix(metrics): sprint status pipeline — 4-layer cheese fix (FDD-OPS-018)
Apr 29, 2026
07a5db6
docs(ingestion): knowledge capture INC-020..023 + v2 status across ex…
Apr 29, 2026
8629781
chore(gitignore): ignore .claude/scheduled_tasks.lock and projects/
Apr 29, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
395 changes: 395 additions & 0 deletions .claude/agents/pulse-ux-reviewer.md

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions .claude/commands/pulse-build.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Target: **$ARGUMENTS**
## Routing

**→ `pulse-product-director`** if: feature spec, persona story, BDD criteria, pricing, UX pattern
**→ `pulse-ux-reviewer`** if: UX/UI review of a page or journey, 3-concept exploration, design editorial hand-off (delivers HTML/CSS/JS + impl spec + FDD backlog)
**→ `pulse-frontend`** if: pulse/pulse-ui/, prototype, HTML/CSS/JS, Chart.js, design tokens
**→ `pulse-engineer`** if: packages/, NestJS, FastAPI, React+Vite, Docker, CI/CD, migrations, Makefile
**→ `pulse-data-engineer`** if: DevLake, Kafka, sync worker, metrics worker, DB schema, pipeline, connectors
Expand Down
1 change: 1 addition & 0 deletions .claude/commands/pulse-review.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ argument-hint: [path-or-review-type] (e.g., "pulse/pulse-ui/", "packages/", "sec

## Routing
- **pulse/pulse-ui/** → `pulse-frontend`: design tokens, semantic HTML, a11y, skeleton states
- **ux / ui / design** → `pulse-ux-reviewer`: page-level UX/UI review — 3 editorial concepts, impl spec hand-off, FDD backlog (prefer `/pulse-ux-review <page>`)
- **packages/** → `pulse-engineer`: architecture compliance, TypeScript strict, Python types, DDD boundaries
- **security** → `pulse-ciso`: RLS, secrets, headers, container security, metadata-only enforcement
- **data-quality** → `pulse-data-engineer`: pipeline idempotency, schema versioning, data observability
Expand Down
85 changes: 85 additions & 0 deletions .claude/commands/pulse-ux-review.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
---
description: Review or redesign the UX/UI of a PULSE page, journey, component or state. Delegates to pulse-ux-reviewer for editorial concepts + implementation spec + FDD backlog.
argument-hint: <page-or-journey> (e.g., "Pipeline Monitor", "DORA dashboard", "Jira Settings", "Onboarding flow", "Home")
---

# UX/UI Review: **$ARGUMENTS**

Delegate to **`pulse-ux-reviewer`** to produce a principal-level UX/UI review of
`$ARGUMENTS` with the three mandatory deliverables.

## Inputs the agent must confirm (or explicitly assume)

1. **Page / journey in scope** — from `$ARGUMENTS`; locate current prototype under
`pulse/pulse-ui/` and/or production route under `pulse/packages/pulse-web/src/routes/`
2. **Primary persona** — Carlos (EM) / Ana (CTO) / Marina (Sr Dev) / Priya (Agile
Coach) / Roberto (CFO) / Lucas (Data Platform)
3. **Top job-to-be-done** — the single decision the page must unlock
4. **Release tag** — MVP / R1 / R2 / R3 / R4
5. **Critical states** — which of loading / empty / healthy / degraded / error / partial
matter most for this page
6. **Data contract** — endpoints, fields, cadence; default to what is shipped in the
production API unless the spec says otherwise
7. **Scale** — assume Webmotors worst case (283 repos, 69 Jira projects, 577 Jenkins
jobs, 373k issues, 63k PRs) unless told otherwise
8. **Anti-surveillance boundary** — confirm author-level data is off-limits

If any input is missing, state the assumption in the deliverable and proceed.

## Expected output (always, in this order)

### A. Three editorial concepts
Each concept comes with:
- Hi-fi screenshot (desktop ≥1280px)
- Hi-fi screenshot of **one** critical alternative state (empty / degraded / incident)
- Drawer or detail view if the concept relies on drill-down
- One responsive view (mobile OR tablet)
- Editorial thesis (3–5 lines)
- Two known limitations

### B. Final recommendation
- Which concept wins and why
- **Three** pre-dev adjustments to the winning concept, each with a short justification

### C. Three mandatory deliverables
1. **Updated frontend code (HTML + CSS + JS)** saved under
`pulse/pulse-ui/<page-path>/` — runnable, uses tokens.css, BEM, ES modules, WCAG AA,
all states, responsive
2. **Implementation spec** at `pulse/docs/ux-specs/<page-slug>-impl-spec.md` — the
contract handed to `pulse-engineer` for componentisation against the design system
3. **FDD backlog** at `pulse/docs/backlog/<page-slug>-backlog.md` — feature cards with
BDD criteria, persona, release, priority, dependencies, estimate, analytics events

## Constraints the agent must respect

- PULSE is **READ-ONLY** against external systems — never design CTAs that trigger
external builds/syncs
- **Anti-surveillance** is non-negotiable — no individual-author data in perf/delay
contexts
- **Real scale** — never design for 3-item lists that collapse at customer scale
- **WCAG AA floor** — status is always colour + icon + label
- **Copy in PT-BR** — direct, professional, no emoji
- **Tokens only** — no hardcoded hex values outside `tokens.css`

## Self-review checklist (agent must confirm all ticks before returning)

- [ ] 3 concepts × (screenshot + alt-state + drawer + responsive + thesis + 2 limitations)
- [ ] Final recommendation + exactly 3 pre-dev adjustments
- [ ] All 6 states (loading / empty / healthy / degraded / error / partial) addressed
- [ ] Responsive spec for desktop / tablet / mobile
- [ ] Real-scale validation — layout survives worst-case customer numbers
- [ ] Anti-surveillance — no individual author in any perf/health context
- [ ] WCAG AA — contrast, labels, focus order, reduced-motion
- [ ] PULSE tokens only — no hardcoded hex
- [ ] PT-BR copy, professional tone
- [ ] Deliverable 1 (code) path returned to user
- [ ] Deliverable 2 (impl spec) path returned to user
- [ ] Deliverable 3 (FDD backlog) path returned to user

## Hand-off

Once the review is complete, the user will typically route:
- The **impl spec** to `pulse-engineer` for React + design system implementation
- The **FDD backlog** to `pulse-product-director` for release planning and
prioritisation against MVP / R1–R4 roadmap
- The **prototype code** stays in `pulse/pulse-ui/` as the reference for visual QA
12 changes: 12 additions & 0 deletions .claude/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"version": "0.0.1",
"configurations": [
{
"name": "pulse-web",
"runtimeExecutable": "npm",
"runtimeArgs": ["run", "dev"],
"port": 5173,
"cwd": "pulse/packages/pulse-web"
}
]
}
63 changes: 63 additions & 0 deletions .githooks/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#!/usr/bin/env bash
#
# PULSE pre-commit hook
# --------------------------------------------------------------------------
# Runs secret-scanning on the staged diff before every commit.
# If a secret is detected, the commit is rejected and the offending
# finding is printed to stderr.
#
# Enable once per clone:
# git config core.hooksPath .githooks
#
# Bypass (only if you are ABSOLUTELY sure it is a false positive and you
# cannot add an allowlist entry in time):
# git commit --no-verify
# (Prefer fixing .gitleaks.toml over bypassing the hook.)
# --------------------------------------------------------------------------

set -euo pipefail

# ------------------------------------------------------------------ colors
if [ -t 2 ]; then
RED=$'\033[31m'; YEL=$'\033[33m'; GRN=$'\033[32m'; DIM=$'\033[2m'; RST=$'\033[0m'
else
RED=""; YEL=""; GRN=""; DIM=""; RST=""
fi

# ------------------------------------------------------------------ gitleaks
if ! command -v gitleaks >/dev/null 2>&1; then
echo "${YEL}[pre-commit]${RST} gitleaks not installed — skipping secret scan."
echo " Install: ${DIM}brew install gitleaks${RST}"
echo " Without it, nothing prevents an API key from entering git history."
exit 0
fi

REPO_ROOT="$(git rev-parse --show-toplevel)"
CONFIG="${REPO_ROOT}/.gitleaks.toml"

CONFIG_ARGS=()
if [ ! -f "${CONFIG}" ]; then
echo "${YEL}[pre-commit]${RST} .gitleaks.toml not found at repo root — running with defaults."
else
CONFIG_ARGS=(--config "${CONFIG}")
fi

echo "${DIM}[pre-commit] scanning staged changes with gitleaks...${RST}"

# `protect --staged` only scans what is in the staged diff — fast and
# scoped to what is about to be committed.
if ! gitleaks protect --staged --redact "${CONFIG_ARGS[@]}" --verbose 2>&1; then
echo ""
echo "${RED}✖ gitleaks found one or more secrets in your staged changes.${RST}"
echo ""
echo "Options:"
echo " 1. Remove the secret from the staged files and rotate it if it was real."
echo " 2. If it is a false positive, add an allowlist entry in .gitleaks.toml"
echo " and commit the config change first."
echo " 3. As a last resort (e.g. offline work, CI will catch it): commit with"
echo " ${DIM}git commit --no-verify${RST} — but you are on the hook if it leaks."
echo ""
exit 1
fi

echo "${GRN}✓ no secrets detected${RST}"
42 changes: 42 additions & 0 deletions .github/workflows/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# GitHub Actions workflows — root vs pulse/

This repo has workflows in **two** locations. The split is intentional.

## `/.github/workflows/` (this directory — **ACTIVE**)

Runs on every push + PR. These are the real gates enforced by branch
protection. Scope is the full monorepo (root-level).

| File | Trigger | What it does |
|---|---|---|
| `ci.yml` | PR + push to main/develop | Gitleaks secrets scan, ESLint + TSC pulse-web, Vitest (139+ tests incl. contract), Vite build |
| `e2e-a11y.yml` | manual + nightly cron | Playwright smoke + axe-core a11y. No-op until backend CI infra is wired — see testing-playbook.md §8.8 |

## `/pulse/.github/workflows/` (sub-directory — **DORMANT**)

Workflows prepared for the day `pulse/` is extracted into its own git
repo (SaaS productization). They expect `pulse/` to be the repo root, so
`cd packages/...` works directly. They do **not** run today because
GitHub Actions only looks at `.github/workflows/` at the actual repo
root.

| File | Purpose |
|---|---|
| `ci.yml` | Full backend + frontend CI (Jest, Pytest with anti-surveillance gate, Docker builds) — runs when pulse/ is standalone |
| `deploy.yml` | Release rollout template (manual dispatch) — TODO steps for kubectl/ECS |

When you extract `pulse/` to its own repo, `git mv pulse/.github/workflows/*.yml
.github/workflows/` and delete these root workflows.

## Branch protection (set once in GitHub Settings)

For `ci.yml` to actually block merges, turn on branch protection for
`main` (and `develop` if used) with these required status checks:

- `Secrets scan (gitleaks)`
- `Lint & typecheck (pulse-web)`
- `Unit tests (pulse-web Vitest)`
- `Build (pulse-web Vite)`

UI path: Settings → Branches → Branch protection rules → Add rule →
"Require status checks to pass before merging" → pick the 4 above.
173 changes: 173 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
name: CI

# Root-level GitHub Actions workflow. Runs on every PR and push to
# main/develop. Matches the Sprint 1.2 quality gates established locally
# (Vitest unit + contract, ESLint, Gitleaks secrets scan) so regressions
# are caught before merge.
#
# Scope note: THIS workflow is frontend + repo-wide only. Backend CI
# (pulse-api Jest, pulse-data Pytest, anti-surveillance gate, Docker builds)
# lives at pulse/.github/workflows/ci.yml and runs when pulse/ is extracted
# into its own repo. See .github/workflows/README.md in the commit message
# for the divided-ownership rationale.
#
# E2E + a11y specs need a live backend (docker compose) and are triggered
# manually via the separate `.github/workflows/e2e-a11y.yml` workflow
# (workflow_dispatch). Once backend CI infra is ready, they'll join this
# pipeline.

on:
pull_request:
branches: [main, develop]
push:
branches: [main, develop]

concurrency:
# Cancel in-progress runs for the same branch on new pushes, but NEVER
# cancel runs on main/develop (they produce artifacts and deploy signals).
group: ci-${{ github.ref }}
cancel-in-progress: ${{ github.ref != 'refs/heads/main' && github.ref != 'refs/heads/develop' }}

env:
NODE_VERSION: "20"

permissions:
contents: read

jobs:
# --------------------------------------------------------------------------
# Secrets scanning — runs first, fast, against full repo (not just diff)
# --------------------------------------------------------------------------
secrets-scan:
name: Secrets scan (gitleaks)
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Checkout (full history)
uses: actions/checkout@v4
with:
# Full history so gitleaks can scan all commits, not just the shallow diff.
fetch-depth: 0

- name: Run gitleaks
# Pinned to a major tag for reproducibility. The action uses the
# .gitleaks.toml at repo root (our config with PULSE-specific rules
# and allowlist for .env / lockfiles / tests/fixtures).
uses: gitleaks/gitleaks-action@v2
env:
# GITHUB_TOKEN is used only to comment on PRs if findings exist —
# no write permissions needed beyond that.
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITLEAKS_CONFIG: ./.gitleaks.toml

# --------------------------------------------------------------------------
# Frontend lint (ESLint + TypeScript)
# --------------------------------------------------------------------------
lint-web:
name: Lint & typecheck (pulse-web)
runs-on: ubuntu-latest
timeout-minutes: 10
defaults:
run:
working-directory: pulse/packages/pulse-web
steps:
- uses: actions/checkout@v4

- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: npm
cache-dependency-path: pulse/packages/pulse-web/package-lock.json

- name: Install pulse-shared (sibling dep)
working-directory: pulse/packages/pulse-shared
run: npm ci

- name: Install pulse-web
run: npm ci

- name: ESLint
run: npm run lint

- name: TypeScript (strict, no emit)
# `tsc -b` validates the project references tree.
run: npx tsc -b --noEmit

# --------------------------------------------------------------------------
# Frontend unit tests (Vitest) — includes component + hook + contract +
# anti-surveillance meta-test. 139+ tests as of Sprint 1.2 step 3.
# --------------------------------------------------------------------------
test-unit-web:
name: Unit tests (pulse-web Vitest)
runs-on: ubuntu-latest
timeout-minutes: 10
defaults:
run:
working-directory: pulse/packages/pulse-web
steps:
- uses: actions/checkout@v4

- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: npm
cache-dependency-path: pulse/packages/pulse-web/package-lock.json

- name: Install pulse-shared (sibling dep)
working-directory: pulse/packages/pulse-shared
run: npm ci

- name: Install pulse-web
run: npm ci

- name: Vitest (run mode, coverage)
# `--run` = no watch, `--coverage` = v8 coverage, output to coverage/.
# Contract tests skip cleanly when backend is offline (CI has none).
run: npm run test:coverage

- name: Upload coverage
if: always()
uses: actions/upload-artifact@v4
with:
name: coverage-pulse-web
path: pulse/packages/pulse-web/coverage/
retention-days: 7

# --------------------------------------------------------------------------
# Frontend build (Vite) — catches type errors that only surface at build time
# --------------------------------------------------------------------------
build-web:
name: Build (pulse-web Vite)
runs-on: ubuntu-latest
timeout-minutes: 10
needs: [lint-web, test-unit-web]
defaults:
run:
working-directory: pulse/packages/pulse-web
steps:
- uses: actions/checkout@v4

- uses: actions/setup-node@v4
with:
node-version: ${{ env.NODE_VERSION }}
cache: npm
cache-dependency-path: pulse/packages/pulse-web/package-lock.json

- name: Install pulse-shared + build (generates dist/ used by pulse-web)
working-directory: pulse/packages/pulse-shared
run: |
npm ci
npm run build

- name: Install pulse-web
run: npm ci

- name: Build
run: npm run build

- name: Upload build artifact
uses: actions/upload-artifact@v4
with:
name: pulse-web-dist
path: pulse/packages/pulse-web/dist/
retention-days: 3
Loading
Loading