Changelog

All notable changes to Soleur.

v3.91.1 — 2026-05-14

  • feat(content): auto-generate article 2026-05-14

v3.91.0 — 2026-05-14

Web Platform

  • feat(auth): NEXT_PUBLIC_DEV_EXTRA_ORIGINS multi-port CSRF allowlist (dev-mode only). Production behavior unchanged.
  • feat(chat): export type StreamEvent from chat-state-machine.ts (folds #2224 line item).
  • feat(e2e): cc-soleur-go-ws-injector.ts Playwright routeWebSocket helper with typed send/sendControl channels and owned pageErrors.
  • feat(e2e): cc-soleur-go-bubbles.e2e.ts — 6 Playwright tests for the 4 cc-soleur-go bubbles. Covers BOTH chip-removal triggers (stream_end AND workflow_started).
  • refactor(e2e): extract shared supabase-mocks helper; dedup start-fresh-onboarding and start-fresh-conversations-rail against it (-184 / +60 lines net).
  • chore(config): widen playwright.config.ts testMatch to array to admit cc-soleur-go-*.e2e.ts to the authenticated project.

Plugin (skills)

  • route plan/SKILL.md Sharp Edges: 1 bullet on plan-prescribed runtime shape verification (library method names against installed types, DOM conditional renders, testMatch glob coverage).
  • route review/SKILL.md Sharp Edges: 1 paragraph on directory-scoped reading of cross-cutting-refactor criterion.

v3.90.1 — 2026-05-14

  • Replace eyJhbGciOiJIUzI1NiJ9.eyJzdW... (entropy 5.2) with low-entropy eyJ<17 a's>.<17 a's>.<17 a's> form in plugins/soleur/skills/incident/test/fixtures/positive-corpus.md. Still triggers the sentinel's JWT regex (eyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}) but bypasses gitleaks default-pack jwt regex (ey[A-Za-z0-9_-]{17,}\.ey[A-Za-z0-9_-]{17,}... — segment 2 starts with a not ey now).

v3.90.0 — 2026-05-14

Plugin

  • New skill: plugins/soleur/skills/incident/ — 9 phases (Phase 0 fact capture → Phase 8 compound-capture handoff). Operator-invoked via /soleur:incident or /soleur:go "production is down".
  • Redaction sentinel (scripts/redact-sentinel.sh, 14 regex classes): JWT, email, UUID, Stripe (sk_/pk_/rk_/whsec_/acct_/cus_/pi_/seti_/sub_/in_), IPv4, env-var, GitHub PAT (ghp_/github_pat_), Anthropic, OpenAI, Supabase (sbp_/sb_secret_/sb_publishable_), PEM private-key headers. Meta-redacted offset output. Exit codes 0/1/2.
  • Pre-write gate — sentinel runs BEFORE Phase 7 inline-emit AND before disk commit. Transcripts are write boundaries.
  • GDPR Art. 33/34 parity blocking (Phase 2) — both acks required when risk_to_subjects: high; only Art. 33 ack when lower-risk.
  • Literal COMMIT-PIR token at Phase 7 — case-sensitive equality after \r + whitespace canonicalization (agent-user parity). Free-form yes is rejected.
  • --dry-run mode — wraps the skill with captured output for greppable ACs (AC8-AC13).
  • /soleur:go intent extension — new incident routing row inserted at line 50 (between review and default).
  • Inspiration: clean-room derivation from alirezarezvani/claude-skills/engineering-team/incident-commander; MIT NOTICE attribution.

Tests

  • plugins/soleur/skills/incident/test/redact-sentinel.test.sh — 19 tests (negative-baseline + 14 regex-class triggers + invalid-arg + output-format).
  • 1053 plugin compliance tests pass (after SKILL_DESCRIPTION_WORD_BUDGET bump 1800 → 1850 for the new skill).

Documentation

  • Spec + brainstorm [Updated 2026-05-13] markers for D1-reversal reciprocal updates.
  • Cross-reference header in canonical PIR (runbooks/dashboard-error-postmortem.md) pointing future PIR scaffolding at /soleur:incident.

v3.89.4 — 2026-05-14

  • feat(legal): DPD §(m) operational telemetry & breach detection user-facing entry

web-v0.85.0 — 2026-05-14

Web Platform

  • feat(auth): NEXT_PUBLIC_DEV_EXTRA_ORIGINS multi-port CSRF allowlist (dev-mode only). Production behavior unchanged.
  • feat(chat): export type StreamEvent from chat-state-machine.ts (folds #2224 line item).
  • feat(e2e): cc-soleur-go-ws-injector.ts Playwright routeWebSocket helper with typed send/sendControl channels and owned pageErrors.
  • feat(e2e): cc-soleur-go-bubbles.e2e.ts — 6 Playwright tests for the 4 cc-soleur-go bubbles. Covers BOTH chip-removal triggers (stream_end AND workflow_started).
  • refactor(e2e): extract shared supabase-mocks helper; dedup start-fresh-onboarding and start-fresh-conversations-rail against it (-184 / +60 lines net).
  • chore(config): widen playwright.config.ts testMatch to array to admit cc-soleur-go-*.e2e.ts to the authenticated project.

Plugin (skills)

  • route plan/SKILL.md Sharp Edges: 1 bullet on plan-prescribed runtime shape verification (library method names against installed types, DOM conditional renders, testMatch glob coverage).
  • route review/SKILL.md Sharp Edges: 1 paragraph on directory-scoped reading of cross-cutting-refactor criterion.

v3.89.3 — 2026-05-13

  • feat(agents): hr-no-dashboard-eyeball-pull-data-yourself

v3.89.2 — 2026-05-13

Plugin (D1 vocabulary canonicalization)

  • Frontmatter key: brand_threshold: (1 file), brand_survival: (5 files), semantic threshold: (4 files) → brand_survival_threshold:
  • Value-form: single-user-incident (50 files) → single-user incident (canonical space form)
  • 6 learning files preserve hyphenated tag-array entries (KB slug convention)
  • 2 protected files preserve threshold: for orthogonal semantics:
    • preflight Check 6 scope-out sentinel (threshold: none, reason:)
    • skill-security-scan test fixture (numeric threshold: 0.5)
  • 3 self-referential files (this PR's plan, tasks.md, session-state.md) preserve their literal token examples (renaming would corrupt the rename's own documentation)
  • kb-tags.txt + INDEX.md auto-regenerated

v3.89.1 — 2026-05-13

Web Platform

  • feat(observability): bind Sentry.setUser with HMAC-pseudonymous user.id at the per-user-rate-limit HOC, wrapped in Sentry.withIsolationScope for cross-request scope isolation under the custom-server boot path.
  • feat(observability): migrate 11 silent-fallback sites in app/**/route.ts to reportSilentFallback + inline setUser; preserves original pino diagnostic message strings and existing Sentry tag continuity (feature/op pairs unchanged).
  • feat(observability): sentry-scrub.ts:scrubRecursive now renames userId/user_id keys (case-insensitive, recursive) to userIdHash at the beforeSend/beforeBreadcrumb boundary. Defensive precedence preserves caller-supplied userIdHash and drops raw key.
  • docs(legal): Article 30 PA8 §(c)(i)+(c)(ii) updated to document the shipped substrate and reference the canonical inventory in sentry-scrub.ts.

v3.89.0 — 2026-05-13

  • feat(cc-router): deny-by-default MCP tool surface + DPA prerequisites (#2909)

v3.88.5 — 2026-05-13

Web Platform

  • Added: pino formatters.log() boundary hook pseudonymises every top-level userId / user_id emission to userIdHash (HMAC-SHA256, Doppler pepper).
  • Added: shared renameUserIdToHash walker (apps/web-platform/server/userid-pseudonymize.ts) — single source of truth for the rename.
  • Hardened: mirrorCrossTenantViolation strips userId/user_id from operator-supplied ctx before Sentry payload spread (defense-in-depth; pino side already covered by the new hook).
  • Updated: Article 30 register PA8 §(c)(ii) — top-level boundary qualification, F2 fail-safe disclosure, DSAR domain-distinct hash field-name documentation.
  • Added: ADR-029 (rename-at-boundary userId pseudonymisation) with invariants I1–I10 including two-primitive separation table.
  • Added: userid-bypass-lint CI gate enforces baseline coverage; new direct logger.error({userId}) sites must route through helpers or emit userIdHash directly.

web-v0.84.0 — 2026-05-13

Web Platform

  • Add hash-user-id npm script + apps/web-platform/scripts/hash-user-id.ts operator CLI for recovering pseudonymous pino log lines from a raw user UUID. Pepper enters via Doppler env injection; never persisted, never typed at the operator terminal.
  • Add apps/web-platform/test/scripts/hash-user-id.test.ts (5 spawnSync tests: happy-path, no-argv, no-pepper, deterministic, 64-hex sanity guard). Tests bypass the npm wrapper to validate the runtime contract directly.

Knowledge Base

  • PA8 §(f) Hetzner pino retention concretised in knowledge-base/legal/article-30-register.md with structural cap, observed-volume sentinel, and closed 4-trigger re-verification list.
  • New runbook knowledge-base/engineering/ops/runbooks/recover-userid-from-pino-stdout.md covering both operator flows. Documents the two-primitive separation (hashUserId vs hashUserIdForSentry) load-bearingly per ADR-029 §I10.
  • knowledge-base/legal/compliance-posture.md Article 30 row appended with concretisation note.

web-v0.83.1 — 2026-05-13

Web Platform

  • feat(observability): bind Sentry.setUser with HMAC-pseudonymous user.id at the per-user-rate-limit HOC, wrapped in Sentry.withIsolationScope for cross-request scope isolation under the custom-server boot path.
  • feat(observability): migrate 11 silent-fallback sites in app/**/route.ts to reportSilentFallback + inline setUser; preserves original pino diagnostic message strings and existing Sentry tag continuity (feature/op pairs unchanged).
  • feat(observability): sentry-scrub.ts:scrubRecursive now renames userId/user_id keys (case-insensitive, recursive) to userIdHash at the beforeSend/beforeBreadcrumb boundary. Defensive precedence preserves caller-supplied userIdHash and drops raw key.
  • docs(legal): Article 30 PA8 §(c)(i)+(c)(ii) updated to document the shipped substrate and reference the canonical inventory in sentry-scrub.ts.

web-v0.83.0 — 2026-05-13

  • feat(cc-router): deny-by-default MCP tool surface + DPA prerequisites (#2909)

web-v0.82.2 — 2026-05-13

Web Platform

  • Added: pino formatters.log() boundary hook pseudonymises every top-level userId / user_id emission to userIdHash (HMAC-SHA256, Doppler pepper).
  • Added: shared renameUserIdToHash walker (apps/web-platform/server/userid-pseudonymize.ts) — single source of truth for the rename.
  • Hardened: mirrorCrossTenantViolation strips userId/user_id from operator-supplied ctx before Sentry payload spread (defense-in-depth; pino side already covered by the new hook).
  • Updated: Article 30 register PA8 §(c)(ii) — top-level boundary qualification, F2 fail-safe disclosure, DSAR domain-distinct hash field-name documentation.
  • Added: ADR-029 (rename-at-boundary userId pseudonymisation) with invariants I1–I10 including two-primitive separation table.
  • Added: userid-bypass-lint CI gate enforces baseline coverage; new direct logger.error({userId}) sites must route through helpers or emit userIdHash directly.

v3.88.4 — 2026-05-12

Web Platform infra

  • Wall-clock cap (ci-deploy-wrapper.sh) enforces 900s SIGTERM + 20s SIGKILL on ci-deploy.sh.
  • TERM/INT trap in ci-deploy.sh writes terminal reason=timeout to the deploy state file when trap CAN dispatch.
  • Six trigger files now tracked by terraform_data.deploy_pipeline_fix (was five).

Soleur plugin

  • deepen-plan skill: new bullet prescribing a 10-line parent.sh/child.sh repro for any AC bound to PGID/session/signal-defer semantics (PGID-inheritance gotcha caught at /work).
  • postmerge/deploy-status-debugging.md: new timeout | 124 taxonomy row with concrete journalctl invocation.
  • ship skill: Deploy Pipeline Fix Drift Gate updated for 6 trigger files; test fixture updated.

v3.88.3 — 2026-05-12

  • feat(ci): split test job into 3 shards + synthetic aggregator (~41% wall-clock reduction)

v3.88.2 — 2026-05-12

Plugin

  • plugins/soleur/skills/one-shot/SKILL.md: new Step 0a.5 between the Linear preflight (0a) and worktree creation (0b).

v3.88.1 — 2026-05-12

  • fix(work,plan): no mid-plan pause gates + operator-step automation gate

v3.88.0 — 2026-05-12

Web Platform

  • NEW GDPR Art. 15 + Art. 20 self-serve export at /dashboard/settings/privacy
  • NEW dsar_export_jobs + dsar_export_audit_pii tables with WORM trigger (migrations 041 + 042)
  • NEW Storage bucket dsar-exports with folder-prefix RLS
  • NEW Account-delete cascade extended for Art. 17 compliance with the new DSAR surface

Plugin

  • NEW .github/workflows/legal-doc-cross-document-gate.yml — blocks DSAR PRs that don't update all 4 legal docs in lockstep
  • NEW Operator runbooks: dsar-export-oversize.md, dsar-export-failed-job.md, scripts/dsar-export-oversize.sh
  • UPDATED Privacy Policy §4.7 + §8.1, GDPR Policy §3.7 + §5.3, Data Protection Disclosure §2.3 + §5.3 + §10.3, compliance-posture.md

🤖 Generated with Claude Code

v3.87.11 — 2026-05-12

Plugin

  • Pre-commit gate: new rule-budget-lint command in lefthook.yml rejects commits when AGENTS.md+AGENTS.core.md exceed 22 k or any rule body exceeds 600 B.
  • Anchor parity: every [skill-enforced: ...] tag must now resolve to a real anchor in its target SKILL.md under a tolerant matcher; the linter resolves all 21 existing pairs against the current tree.
  • Shared SECTIONS module: scripts/_agents_md_sections.py is the single source of truth.

v3.87.10 — 2026-05-12

Plugin (hooks + skills)

  • New: .claude/hooks/lib/session-state.shacquire_lock/release_lock/acquire_lock_shared/with_lock (per-name FD multiplexing via exec {fd}>>file, flock-based), acquire_lease/release_lease/is_lease_active/sweep_orphan_leases/_register_lease_release_trap (durable key=value leases with PID + hostname + started_at Flohr-rule release-guard, ISO-8601-Z anchored to defend date -d against natural-language DoS, path-traversal validator on worktree names), headless_or_stderr (TTY-aware routing — log file under claude --bg, stderr foreground), SOLEUR_DISABLE_SESSION_STATE=1 kill switch. Hard-fails with operator-facing error if flock missing. 349 LOC + 349 LOC tests (T1–T8 covering mutual exclusion, timeout, lease roundtrip, dead-PID detection, orphan sweep, flock-missing hard-fail, multi-signal trap, headless/foreground branch).
  • Edit: plugins/soleur/skills/git-worktree/scripts/worktree-manager.sh — sources session-state.sh with loud-warn fallback; create_for_feature calls sweep_orphan_leases + acquire_lease + _register_lease_release_trap + git push -u + ls-remote verify, emits SOLEUR_FEATURE_PUSH_FAILED marker on stdout when push fails; cleanup_merged_worktrees acquires cleanup-merged lock (5s timeout) with RETURN trap, nested fetch-prune lock, reap loop checks is_lease_active + 10-min recent-commit grace + clock-skew abs guard before existing dirty-status guard.
  • Edit: .claude/hooks/pre-merge-rebase.sh — 4 stderr emissions routed through headless_or_stderr; git merge origin/main wrapped in acquire_lock rebase-main 60 with EXIT trap; command-detection regex extended to match ---separator wrapped forms (closes hook-bypass class).
  • Edit: .claude/hooks/lib/log-rotation.sh + .claude/hooks/lib/incidents.sh — stderr emissions routed through headless_or_stderr with lazy-source guard.
  • Edit: .claude/hooks/session-rules-loader.sh — boolean HEADLESS_MODE export ([[ ! -t 0 && -n $CLAUDECODE ]]) for downstream consumers.
  • Edit: plugins/soleur/skills/{one-shot,brainstorm,work}/SKILL.md — invoke worktree-manager.sh feature with SOLEUR_SKILL_NAME + SOLEUR_EXPECTED_DURATION_MIN env to wire the session lease.
  • Edit: plugins/soleur/skills/{ship,merge-pr,schedule,product-roadmap}/SKILL.mdgh pr merge --auto wrapped in with_lock merge-main 600 --, with rc=99 retry guidance.
  • Edit: plugins/soleur/skills/work/SKILL.md — explicit Phase Exit release_lease block.
  • Edit: plugins/soleur/skills/{plan,review}/SKILL.md — Sharp Edges entries for "shell wrappers can bypass PreToolUse hook regex" (routed from compound learning).

Tests

  • .claude/hooks/lib/session-state.test.sh (T1–T8)
  • plugins/soleur/skills/git-worktree/test/lease-protects-active.test.sh (2026-04-21 reproducer; verified RED→GREEN with commit-date 2025-01-01 to bypass recent-commit grace and isolate the lease guard)
  • .claude/hooks/pre-merge-rebase-headless.test.sh
  • plugins/soleur/test/concurrent-ship.test.sh (static lock-wiring assertion across 4 SKILL.md files + smoke serialization test)
  • .claude/hooks/session-rules-loader-headless.test.sh
  • test/pre-merge-rebase.test.ts — strip CLAUDECODE from cleanEnv so spawned hooks use the foreground stderr branch
  • .claude/hooks/log-rotation.test.sh Test 14 — updated for new stderr format

v3.87.9 — 2026-05-12

Web Platform

  • feat: pseudonymize userId at Sentry + pino emit boundary in apps/web-platform/server/observability.ts (HMAC-SHA256, fail-closed sentinel, optional rotation-lookup pepper arg).
  • feat: migrate 2 direct Sentry.captureMessage 23505-fallback sites in ws-handler.ts to warnSilentFallback.
  • chore: add SENTRY_USERID_PEPPER + pepper to sensitive-keys.ts redaction list.
  • chore: explicit isolate: true on vitest unit project for module-init env-var isolation.

Legal

  • docs: Article 30 PA8 §(c) — disclose HMAC-SHA256 pseudonymization at helper boundaries with forward-reference to #3698 for the 27-site direct-pino-emit migration.
  • docs: Article 30 PA8 §(f) — append Recital 26 retention-only Art. 17 clarification.

Plan Skill

  • docs: Sharp Edges — centralizing helper / boundary / redaction layer transforms require two-clause ACs (helper-routed AND direct-bypass) AND scoped disclosure language. See 2026-05-12-centralized-at-helper-boundary-transforms-overclaim-in-acs-and-disclosures.md.

v3.87.8 — 2026-05-12

Plugin

  • plugins/soleur/skills/work/SKILL.md Phase 4 — entry-guard subsection between Playwright-First Audit and Invocation Mode. Asserts at least one commit beyond the upstream branch before emitting the handoff marker; distinct exit codes (2 = pause-and-commit, 1 = halt-and-investigate); detached-HEAD guard.
  • plugins/soleur/skills/plan/SKILL.md and plugins/soleur/skills/deepen-plan/SKILL.md — matching loader-class-fit checklist bullets with cross-mirror HTML comments. Pins grep at the canonical class-selection range.
  • plugins/soleur/skills/compound/SKILL.md step 8 [CRITICAL] warning — appended Why-line trim semantics directive (with Correct/Over-trimmed examples) and pre-demotion class-fit reminder.
  • AGENTS.docs.md cq-agents-md-why-single-line rule — extended [skill-enforced:] tag suffix to name the two enforcement dimensions; trimmed Rule count advisory. and second (compound step 8) parenthetical for headroom (594 → 578 B / 600 cap).

Knowledge base

  • knowledge-base/project/learnings/2026-05-12-agents-md-trim-loader-class-fit-verification.md — captures (a) loader-class-fit verification at plan time, (b) push semantic detail into [skill-enforced:] tag suffix instead of rule body. Generalization: AGENTS.md is the index, not the spec — let the enforcer own the semantics.
  • knowledge-base/project/plans/2026-05-12-chore-agents-md-trim-workflow-hardening-plan.md — implementation plan.
  • knowledge-base/project/specs/feat-one-shot-3682-agents-md-trim-workflow-hardening/session-state.md — session-state forwarded from the plan+deepen subagent.

v3.87.7 — 2026-05-12

Plugin

  • Rule registry: 1 wg-* demoted core→rest, 1 wg-* body-trimmed in core, 2 hr-* body-trimmed in core, 4 Why-line trims.
  • plugins/soleur/skills/work/SKILL.md: added Type-widening cross-consumer grep bullet in §Phase 0.

Web Platform

  • apps/web-platform/test/pdf-text-extract.test.ts: beforeAll pre-warms pdfjs-dist (fixes 7s cold-start flake; subsequent tests run at warm ~9ms).

Knowledge-base

  • Plan + learning + session-state files documenting the trim strategy and 3 session errors → workflow improvement follow-up at #3682.

v3.87.6 — 2026-05-12

Plugin

  • Plugin-mirror DPD §4.2 Resend Legal-Basis column trimmed to match the canonical surface; Last-Updated annotation rewritten to reference §2.3(j) instead of workflow tokens.

Canonical legal docs

  • Canonical DPD §4.2 Resend Legal-Basis column trimmed; Last-Updated annotation refreshed.

v3.87.5 — 2026-05-12

  • refactor(cc-dispatcher): cluster drain (#3639 + #3640 + #3641 + #3642)

v3.87.4 — 2026-05-12

Plugin

  • New plan/SKILL.md Sharp Edges: precondition-grep on producing scope, parametrized-test ↔ component-prop-boundary cross-check, single-enum FR enumeration.
  • New review/SKILL.md Defect Class: single-literal gate over multi-member union/enum, with spawn-prompt enumeration takeaway.

v3.87.3 — 2026-05-12

  • docs: defer #2724 mcp-server-builder (brainstorm)

v3.87.2 — 2026-05-12

  • Forward-ports plugin-mirror legal docs at plugins/soleur/docs/pages/legal/* to match canonical disclosures on Web Platform push notifications, Resend transactional email, KB-sharing lawful basis, and Article 30 register activity #11. Documentation-only; no code, schema, or processing changes. Public docs-site at soleur.ai/legal/* will now reflect the same Web Platform processing activities already disclosed at app.soleur.ai/legal/*.

View all releases on GitHub →

Frequently Asked Questions

How often is Soleur updated?

Soleur ships continuously — updates are released when ready and tagged with semantic versioning. There is no fixed release schedule. Changes range from new agents and skills to bug fixes and documentation improvements.

How do I upgrade Soleur?

Run claude plugin install soleur to get the latest version. The plugin manager handles the update automatically. Check the changelog or GitHub releases page for details on what changed.

Does Soleur use semantic versioning?

Yes. Soleur follows semantic versioning — major versions for breaking changes, minor versions for new agents or skills, and patch versions for bug fixes and documentation updates. Version labels are set during PR review and applied automatically at merge.

Stay in the loop

Monthly updates about Soleur — new agents, skills, and what we're building next.