Browser smoke (Playwright) revealed that rewriting path internally without
changing the response URL left the browser's base URL as /, breaking
relative <script src="dashboard.js"> and ../automation-graph-data.js
references. 302 redirect makes the browser settle on /docs/observer/,
which resolves the relative paths correctly. All 4 views verified clean
(0 console errors). Screenshots: brain-dashboard-{map,replay,feed,aggregate}-view.png.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Worktree has no app/node_modules — vitest not run here; final regression
deferred to main-checkout post parallel-session release. Logic is a 7-line
pure filter; tests cover empty filter, classification, errors-only.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The config's include `../tools/*.test.mjs` resolves relative to its
own dir (app/), not cwd. Baseline verified 2026-05-19 from app/:
11 files, 169 tests passing, 0 failures.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Standalone HTML dashboard that visualises the observer episode log over
the automation-graph topology — 4 views (map / task-replay / session
feed / aggregate), graph as shared canvas, 3-phase build order.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Логин-страница уже в состоянии networkidle → waitForLoadState резолвился
мгновенно (до пост-логин редиректа), скрипт хватал PHPSESSID
неаутентифицированной логин-страницы. CSV-сверка 11:00 (19.05) упала
"load-reports returned non-array response" — портал отдал HTTP 200
+ HTML логин-страницы вместо JSON-массива отчётов.
После клика submit:
- waitForFunction опрашивает исчезновение #loginform-username из DOM
(переживает навигацию);
- guard exit 1, если форма осталась — отклонённый логин больше не
маскируется под «успех» (exit 0).
Verified: 2× RefreshSupplierSessionJob → валидная сессия (load-reports
JSON-массив из 39 отчётов); CsvReconcileJob id=7 status=ok.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
core.autocrlf=true rewrites .mjs to CRLF in the working tree on
checkout/rebase. vitest fails to load CRLF .mjs files with imports
(SyntaxError: Invalid or unexpected token, no location) — node --check
and esbuild tolerate it, only vitest's transform breaks. `*.mjs text
eol=lf` pins LF in the working tree regardless of autocrlf.
See memory quirk #100. Repo blobs were already LF — no content change.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
#1 — detectAskUserQuestionChoice: when a turn contains an AskUserQuestion
whose answer exactly matches an offered option label, classify as
user_chose_from_options. The answered entry carries a structured
toolUseResult (questions[].options[].label + answers map). A custom
"Other" free-text answer is NOT a pick — falls through. Wired into
parseTranscript after the text-list detector.
#3 — parallel_session: dropped broad word matches (параллельн /
"parallel session") that false-fired on any casual mention. Now only
strong collision evidence (foreign git index / чужой staged /
index.lock / another git process). Best-effort per spec R2 — prefer
false-negative over false-positive.
169/169 tools tests GREEN (+9 new).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Header «Версия» line lagged at 2.18 while §9 already carried v2.19
(factor-analysis extension) and v2.20 (phase 1.1) entries — pre-existing
drift from f7f37fb. Header now reflects actual latest version; v2.18
summary demoted to «v2.18 наследие». Full per-version detail stays in §9.
Через /claude-md-management:claude-md-improver (§5 п.10).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Root cause (systematic-debugging): isRealUserPrompt treated skill-content
("Base directory for this skill:"), local-command output
(<local-command-stdout>), and interrupt markers as genuine prompts.
findTurnStart then anchored a turn on the synthetic message — the turn
slice missed the genuine prompt's UserPromptSubmit hook_additional_context
attachment → economy_level: null, wrong prompt_signal/task_classification.
Same cause made extractLastUserPromptText return skill content, so the
Stop-hook routing-gate false-positive-blocked autonomous §12 skill
invocations (detectMethodDirected saw the node name in skill text).
Fix: SYNTHETIC_PROMPT_MARKERS + isSyntheticPrompt — isRealUserPrompt
returns false for synthetic messages. One fix closes both the
economy_level capture gap and the 2nd routing-gate FP class.
160/160 tools tests GREEN (+3 new).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Строка метрик начиналась с «+ 121 индекс» после переноса → markdownlint
MD004/MD032 (трактовал как list-item). Переформулирована через запятые.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Финальное code-review вскрыло CRITICAL: dedup-сверка findOnPortal и
manualQueueResolve матчат строки портала по {platform, signal_type,
unique_key}, но listProjects отдавал сырое тело rt-projects-load.
Сырая форма (verified из recon-снапшота 2026-05-19):
- ответ — конверт {projects:[443 строки], tags, users, ...}, НЕ голый массив
→ listProjects возвращал весь dict, findOnPortal итерировал по ключам
конверта (projects/tags/...) вместо строк проектов;
- строка проекта: {id, name:"B<n>_<key>", type:"hosts|calls|sms", content}
— без platform/signal_type/unique_key.
Фикс:
- SupplierPortalClient::listProjects — извлекает body['projects'].
- AjaxProjectChannel::listProjects — нормализует сырые строки в контракт
SupplierProjectChannel: platform <- префикс name "B<n>_", signal_type <-
type (hosts->site/calls->call/sms->sms), unique_key <- content. Сырые
поля сохранены. findOnPortal + manualQueueResolve матчат корректно.
- AjaxProjectChannelTest — тест нормализации против фактической формы
портала (не идеального мока); SupplierPortalClientRtProjectTest —
listProjects против конверта {projects}.
Также (code-review I1): findOnPortal catch — Log::warning проглоченного
исключения, иначе провал дедупа невидим (молчаливый дубль rt-проекта).
Code-review I2 (partial-unique индекс supplier_manual_sync_queue от
дубль-эскалаций при job-retry) и I3 (lockForUpdate в manualQueueResolve) —
follow-up до прод-релиза (эпик гейтится Б-1, не в проде).
Регрессия Pest 973/970/0 / 3 skipped.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Таблица pending-записей яруса 3 + кнопка «Отметить выполнено» с confirm-
диалогом, дёргает POST .../manual-queue/{id}/resolve. Реюз существующего
админ-экрана интеграции с поставщиком (после «Истории сверок»).
NB: spec в tests/Frontend/ (vitest include — tests/Frontend/**, не
resources/.../__tests__/ как указал план Step 11.1). loadManualQueue
defensive Array.isArray-guard — иначе onMounted в чужих spec'ах
(mockResolvedValue без queue-ключа) ловил undefined.length.
Spec §4.6. Task 11 of 12. Vitest 5/5 (2 новых + 3 существующих).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
GET /api/admin/supplier-integration/manual-queue — pending список (limit 100).
POST /manual-queue/{id}/resolve — оператор пометил, что вручную создал проект
на портале; reconcile через channel->listProjects() по (platform, signal_type,
unique_key), 409 если не найден.
ОТКЛОНЕНИЕ ОТ plan Step 10.3: план писал portal external_id прямо в
projects.supplier_b*_project_id (FK на local supplier_projects.id) — FK
violation. Resolve делает firstOrCreate local supplier_projects row с
verified external_id, в FK пишет local id.
Routes — в группе saas-admin (web.php, EnsureSaasAdmin стаб). Task 10 of 12.
Tests 4/4 (index pending / exclude resolved / resolve match / resolve 409).
Spec §4.6.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Запас ~3 часа до портального дедлайна 21:00 — эскалация на ярус 2/3
(медленный браузер / ручной оператор) происходит в рабочее время.
RefreshSupplierSessionJob daily — на 15 мин раньше sync (17:45).
Hourly RefreshSupplierSessionJob — без изменений.
Spec §4.7. Task 9 of 12. Tests 2/2 (cron expression + timezone).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Оба job'а инжектят SupplierProjectChannel (DI → FailoverProjectChannel)
вместо прямого SupplierPortalClient. Catch TierEscalatedException +
WindowDeferredException — эскалация/перенос пропускают элемент, не валят job.
SyncSupplierProjectJob (singular): handle переписан — find-or-create local
supplier_projects row, portal-create через channel. ОТКЛОНЕНИЕ ОТ plan Step 8.1:
план писал channel-результат (portal external_id) прямо в projects.supplier_b*_
project_id, но эта колонка — FK на supplier_projects.id (local), не portal id.
Сохранена семантика ensureSupplierProject — job создаёт local row с
supplier_external_id и пишет в FK local id. ensureSupplierProject удалён из
SupplierPortalClient (был единственный consumer — этот job).
SyncSupplierProjectsJob (plural): handle/syncOne принимают channel; create →
createProjectForLiderra, update → updateProjectForLiderra (context-project из
liderraProjects->first() для project_id в очереди яруса 3).
Tests: singular переписан под SupplierProjectChannel mock (6 tests, incl.
idempotency reuse); plural — handle(AjaxProjectChannel) для non-failover
ветки (Http::fake-контракт сохранён). Larastan отложен на T12 (worktree
quirk — гонится в основной копии). Регрессия Pest 966/963/0 / 3 skipped.
Spec §5. Task 8 of 12.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
create/update/list через headless Chromium по образцу refresh-session.js.
Селекторы зафиксированы из recon-снапшота rt-add-project-form.yml (Task 1).
stdin/stdout JSON, exit codes 0/1/2/3/4 (success/auth/selector/timeout/input).
Фикстурный тест против локального HTML — без живого портала. Runner —
встроенный node:test (app/playwright не использует @playwright/test, только
playwright core); skipLogin режим открывает фикстуру напрямую.
Spec §4.3. Task 6 of 12. Node-тесты 2/2.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
listProjects() матч по (platform, signal_type, unique_key) до create.
Защита от дубля при полу-успехе яруса 1 (create прошёл на портале, но
локальная запись не сохранилась → следующий запуск дублировал бы).
listProjects-сбой проглатывается — ярус-эскалация всё равно покроет.
Spec §4.4 шаг 2, §7. Task 5 of 12. Тесты 7/7 (19 assertions).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Live discovery через Playwright MCP (Task 1):
- создан LIDPOTOK_TEST_DELETE_ME (B1+B2+B3) → 3 rt-проекта на портале;
- записаны сетевые запросы /admin/visit/rt-*;
- все три проекта удалены вручную, портал чист.
Endpoints (verified):
- POST /admin/visit/rt-project-save (create id:0, update id:N — same URL)
- POST /admin/visit/rt-project-delete (id строкой)
- GET /admin/visit/rt-projects-load?src=none
Все три — application/json. Конверт ответа:
- success: HTTP 200 + {status:OK, message, result, id?:string}
- error: HTTP 200 + {status:Error, message, result:null}
ID — строка (12721245), приводится к int (fits в int64).
Один save с B1+B2+B3 включёнными создаёт 3 rt-проекта — toPayload()
шлёт ровно один платформенный флаг (srcrt|srcbl|srcmt).
SupplierPortalClient:
- docblock переписан под verified контракт
- listProjects: путь /admin/visit/rt-projects-load + ?src=none query
- saveProject: путь /admin/visit/rt-project-save, asJson, парсинг id
- updateProject: тот же endpoint что save, id:N в body
- deleteProject: путь /admin/visit/rt-project-delete, asJson, id строкой
- new assertStatusOk() — HTTP 200 + status:Error → SupplierClientException
- toPayload(): полный Vuex-payload с маппингом DTO → portal:
- platform B1/B2/B3 → srcrt/srcbl/srcmt (single-true)
- signalType site/call/sms → type:hosts/calls/sms
- workdays int[] → string[]
- status active/paused → bool
- + tag:_lidpotok, name/content из uniqueKey, defaults для show/depth/etc
Tests:
- new: tests/Feature/Supplier/SupplierPortalClientRtProjectTest.php (7 tests,
contract: save+update+delete+list + 2 status:Error error-paths + B2/calls
mapping)
- Sync/Cleanup/Unit тесты обновлены под новый URL + envelope shape.
Закрывает spec §1 honest-caveat «placeholder, не верифицирован»
и журнал решений запись 9. Регрессия: Pest 944/941/0 failed / 3 skipped
/ 2768 assertions / 59.2s.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
buildFactorMatrix already buckets decision_provenance.kind dynamically
(brain-retro-analyzer.mjs:112) — no production change needed. Test
pins that user_chose_from_options is counted on the provenance axis.
12/12 brain-retro tests GREEN.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
When episode is user_chose_from_options, routing-gate does NOT block —
collaborative-choice from Claude-offered options doesn't require a
routing-tag (detector is deterministic). 18/18 stop-hook tests GREEN.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
detectChoiceProvenance runs BEFORE parseRoutingTag; if last assistant
turn offered options and user prompt references one, decision_provenance
becomes user_chose_from_options. Otherwise falls back to existing
routing-tag / autonomous logic.
3 new parser tests GREEN; all existing tests still GREEN (43/43).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Pure module — extracts options (numbered/lettered/bullets/AskUserQuestion)
from last assistant message, detects user reference (position-based +
substring), returns decision_provenance for the 3rd kind.
23/23 tests GREEN.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds 3rd decision_provenance kind for collaborative-choice case
(user picks one of options Claude offered). Distinct from
user_directed_method: counterfactual = Claude's recommended option,
not "what Claude would have done autonomously". Routing-gate does
NOT block this kind — collaborative choice from Claude-designed
choice-space.
Trigger: 19.05.2026 live false-positives — "1 экономия 0%",
"в делаем", "делай 2" classified as user_directed_method.
§11 + 8 subsections; 7-attribute decision_provenance schema;
new tools/observer-choice-detector.mjs (pure module); parser
+routing-gate +/brain-retro extensions.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Pure deterministic Layer-4 aggregation module (spec §6) for the /brain-retro
skill. Exports: dedupeEpisodes, inferOutcome, groupEpisodesToTasks,
findCausalChains, buildFactorMatrix, analyze. Read-only — never writes JSONL.
11/11 tests green. CLI smoke: 10 real episodes → valid JSON with all 5 keys.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Русская проектная лексика для плана резерва канала миграции проектов
(docs/superpowers/plans/2026-05-19-supplier-project-channel-failover.md).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
12-task plan implementing the spec
docs/superpowers/specs/2026-05-19-observer-factor-analysis-design.md
in 4 layers (schema v2 + capture + enforcement + analysis) plus
normative sync. Each task has TDD steps with full code.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Design for making the brain governance observer rich enough for real
factor analysis. Surfaced during a discussion with the owner: the
observer is "paper-complete" but episodes lack the data factor analysis
needs — the outcome is a hardcoded "success", there is no decision
provenance (who chose the node — Claude autonomously, or the owner
forcing a method), no environment factors, no task grouping.
4-layer architecture:
- Layer 1 — episode schema v2: decision_provenance (+ counterfactual),
environment block, task_size, real outcome enum, task_ref.
- Layer 2 — capture: deterministic transcript parsing for all factors +
a one-line routing tag (owner-forced-method only).
- Layer 3 — two-sided enforcement: 3a routing-gate (Stop-hook blocks the
turn until the tag is present — unbypassable by Claude); 3b observer
self-discipline (silent failures become recorded observer_error
markers; coverage + registration verified by a controller).
- Layer 4 — analysis: /brain-retro infers real outcome from the next
episode's opening prompt, groups episodes into tasks, correlates
causal chains, builds the factor matrix.
Scope: everything except an independent agent-judge — that, plus
confusion_marker as a real judgment and real-time friction flags, is
phase 2 (separate spec).
Brainstormed via superpowers:brainstorming. Next: writing-plans.
Refs: ADR-011, spec 2026-05-19-brain-governance-design.md, Pravila §16.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The committed STATUS.md was stale (generated 2026-05-19T03:49, before
the C1/C2 strict-mode fixes and before the post-commit hook existed):
it showed C1/C2 🔴 and "0 episodes". Regenerated via the now-installed
post-commit hook (C4 status-md job) — C1/C2/C3/C4 all ✅, 5 episodes.
Context: `.git/hooks/post-commit` was never installed, so the C4
status-md job (lefthook post-commit) never ran automatically. Fixed
locally via `lefthook install --force` (installs pre-commit/post-commit/
pre-push). The hook files live in `.git/` and are not version-tracked —
re-run `lefthook install` after clone if hooks go missing.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The Stop-hook was writing empty-shell episodes (task_id "unknown-<ts>",
node_chosen "unknown", events []). Root cause: buildEpisodeFromContext
read fields from the Stop-event stdin that Claude Code never sends
(primary_rationale, node_chosen, ...) and the session field name was
wrong (ctx.sessionId camelCase vs Claude Code's session_id). The hook
never read transcript_path — the only real source of session data.
New tools/observer-transcript-parser.mjs — pure parseTranscript(text,
fallbackSessionId):
- Scopes to the last turn (from the last real user prompt to EOF) —
one episode == one prompt→response cycle. A tool_result-carrier user
message is not treated as a turn boundary.
- Extracts task_id (real sessionId), timestamps (real duration),
skill_invoked events, a tool_summary event with per-tool counts,
error events (tool_result is_error), node_chosen (first skill, else
"direct"), hard_floor (invoked when a superpowers:* skill is used),
path_type (regulated/improvised), task_classification (keyword
heuristic on the prompt).
- Reasoning fields triggers_matched/candidates_considered/
boundaries_applied stay [] — not recoverable from a transcript;
their capture is a separate ADR-011 follow-up.
observer-stop-hook.mjs: reads ctx.transcript_path + ctx.session_id
(camelCase fallback kept), readFileSync best-effort, delegates to
parseTranscript. No transcript → graceful fallback to ctx defaults.
Episode schema (5 mandatory + 7-field primary_rationale) unchanged —
no normative change. Stop-event is never blocked (exit 0 on any error).
TDD: 17 parseTranscript tests + 1 buildEpisodeFromContext transcript
test. Full tools Vitest 70/70 GREEN. CLI smoke against a real 575-entry
transcript: episode populated — real task_id, ~6.5 min duration,
tool_summary {Bash:5,Read:5,Grep:1,Edit:9,Write:1}, error event.
Refs: ADR-011 brain governance §6.2 (observer evidence loop).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Removes the `missingInSettings` reverse check ("plugin documented in
Tooling but disabled in settings.json"). It was broken by design:
Tooling Прил. Н lists tools by human/group name ("Frontend Design
plugin", "Trail of Bits Skills") while settings.json keys are machine
IDs (`name@marketplace`) — the two namespaces never compare. The
`/#\d+\s+([\w-]+(?:@[\w-]+)?)/` scan also captured the first plain word
after "#NN" ("#1 PostgreSQL MCP" → "PostgreSQL"), so every run emitted
~190 lines of WARN noise.
ADR-011 §6.1 specifies only the settings→Tooling direction (the L1
pattern "plugin enabled without Tooling formalization"). That is the
FAIL path and is unchanged. detectDrift now returns `{ missingInTooling }`
only. CLI output is a clean single line on success.
Closes the cosmetic issue flagged in bffdaa9.
TDD: reverse-check test replaced with `not.toHaveProperty
('missingInSettings')`; 12/12 GREEN. Smoke: node tools/l1-watcher.mjs
-> exit 0, "OK — 0 drift" (no WARN block).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Removes the `|| true` WARN-only guard from pre-commit jobs 11
(l1-watcher) and 12 (cross-ref-checker). Both controllers now block
the commit on real drift.
Safe to flip now that the false-positive sources are closed:
- C1: tools/.l1-watcher-aliases.txt resolves the 9 name@source drifts
(Frontend Design plugin, Trail of Bits Skills group).
- C2: link-anchored detection + history-block scope-cut removes the
~150 «наследие»/arrow-transition false positives.
Verified on the current tree: node tools/l1-watcher.mjs -> exit 0,
node tools/cross-ref-checker.mjs -> exit 0. Comment blocks and
fail_text updated to describe strict behaviour and the alias escape
hatch.
Refs: ADR-011 brain governance §6.1 / §6.2.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Closes the ~150 false drifts that prevented strict mode. The old regex
`\b(Name)\s+v(\d+\.\d+)` swept the whole file head and matched every
historical version mention, plus the FROM-side of arrow transitions
("v1.30→v1.31"). Real current-vs-header drift in the repo: zero.
Two-tier detection:
- Primary LINK_REF_RE: a markdown-link to a normative file followed by
the first bold version — "[..](docs/Tooling_v8_3.md) (**Прил. Н
v2.17**". Link anchor makes it immune to history-block noise. This is
how CLAUDE.md §0 cross-refs table is written, so CLAUDE.md is fully
validated. Runs on the whole file.
- Fallback CROSS_REF_RE: plain "Name vX.Y" mention, scoped to the text
*before* the first history block. Pravila/Tooling/PSR_v1 have no
markdown-link cross-refs, so the fallback covers them — but their
shapki list past releases, so the scan stops at the first history
marker (`**vN.M наследие**` / `**Что изменилось в vN.M относительно**`
/ `**vN.M** — `). dedupe-by-target keeps the first ref per target.
Regex hardening:
- `\b` after the version forbids backtracking to a partial capture
(so "v1.30→" never collapses to a spurious "v1.3" match).
- `(?!\s*→)` negative lookahead drops the FROM-side of transitions.
TDD: 8 new tests (link-based, "Прил. Н" prefix, multi-file table,
dedupe, two arrow shapes, three history-marker shapes, link-beats-
fallback). 18/18 GREEN.
Smoke: node tools/cross-ref-checker.mjs -> exit 0, "OK — 0 drift in
4 files" (Pravila/CLAUDE.md/Tooling/PSR_v1; MEMORY.md is outside the
repo by design — existsSync-skipped).
Refs: ADR-011 brain governance §6.2 (C2 cross-ref consistency detector).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Closes the 9 pre-existing name@source drifts that prevented strict mode:
settings.json lists each marketplace plugin by machine name (e.g.
"frontend-design@claude-plugins-official"), while Tooling Прил. Н
describes them under a human/group name (e.g. "Frontend Design plugin",
"Trail of Bits Skills" — single row #39 for 8 sub-plugins).
Mechanism:
- tools/.l1-watcher-aliases.txt — settings_name=tooling_substring map.
- detectDrift(settings, tooling, aliases): direct match first, then
alias-substring fallback. Settings name considered formalized if
Tooling text includes either the name itself or aliases[name].
- parseAliases(raw) exported — line-based KV parser with #-comments
and split-on-first-= semantics (values may contain "=").
TDD: 6 new tests (3 detectDrift + 4 parseAliases). 12/12 GREEN.
Smoke: node tools/l1-watcher.mjs -> exit 0, "OK — 0 drift".
Known cosmetic baseline issue (pre-existing, not introduced here):
the missingInSettings WARN list is noisy — regex
/#\d+\s+([\w-]+(?:@[\w-]+)?)/g captures the first \w+ after "#NN"
even when it is a plain word (e.g. "#1 PostgreSQL MCP" -> "PostgreSQL"),
producing ~190 WARN entries. WARN is non-blocking, so strict mode flip
in Phase 3 is unaffected; a follow-up filter on names containing "@"
would silence this without behavioural change.
Refs: ADR-011 brain governance §6.1 (C1 L1-watcher detector for the
"plugin in settings.json without Tooling formalization" L1 pattern).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Memory files (e.g. feedback_brain_unused_tools_not_problem.md) live
in C:/Users/.../memory/, OUTSIDE the git repo. Markdown link from
docs/observer/STATUS.md (relative path) resolved to non-existent
in-repo path → lychee broken-link error in pre-push gate.
Fix: plain-text mention of memory key (no markdown link), with
explicit note «outside-repo memory store». Generator updated
accordingly; 31/31 Vitest tests still GREEN.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
pre-commit jobs 11-13:
- l1-watcher (WARN-only via || true; glob settings.json + Tooling)
- cross-ref-checker (WARN-only via || true; glob 5 normative files)
- observer-of-observer (always exit 0 by design)
post-commit job 14:
- status-md (regenerates docs/observer/STATUS.md + stages it for
next commit; never fails commit via || true)
Both l1-watcher and cross-ref-checker are WARN-only initially because:
- l1-watcher surfaces 9 known pre-existing 'name@source' drifts
(see commit 4382de3); strict mode pending alias resolution.
- cross-ref-checker surfaces noise from historical «наследие» entries
in headers (see commit a780959 DWC); strict mode pending refinement.
observer-of-observer is warn-only by spec (no fail until C3 prune
threshold 54 weeks).
Verified via npx lefthook run pre-commit on staged lefthook.yml —
all 14 jobs evaluate cleanly: 9 skipped (glob mismatch), 5 ran
(including new observer-of-observer warn).
Per ADR-011 + plan Task C5.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Aggregates C1/C2/C3 outputs via execFileSync (Security Guidance #40
compliant — uses fixed args array, no shell injection surface) +
observer episode count. Behavioral rule embedded in metric copy.
Per ADR-011 + spec §6.4.
3 Vitest tests GREEN (31/31 total).
Smoke run rebuilds STATUS.md with current state:
- C1 🔴 (l1-watcher surfaces 9 plugins in settings not formalized
in Tooling Прил. Н by exact name@source — see commit 4382de3)
- C2 🔴 (cross-ref-checker surfaces noise from 'наследие' headers
— see commit a780959 DWC)
- C3 ✅ (0 weeks since last read)
- C4 ✅ (this file)
Both 🔴 states surface known pre-existing drift (not regressions).
C5 lefthook wiring will handle WARN-vs-FAIL semantics.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Pure regex/JSON, 0 LLM calls. 5 Vitest tests GREEN (23/23 total).
Per ADR-011 + spec §6.2.
Smoke run on real repo surfaces ~150 «drifts» — these are
**historical 'наследие' entries** in headers (CLAUDE.md / Pravila /
Tooling / PSR_v1), not actual current cross-ref mismatches. Each
of these 4 files has a multi-line «v2.X наследие:» / «v1.Y наследие:»
chain in its top header describing past sub-versions; my 50-line
scan picks them all up.
CONCERN: mechanism is correct (test fixtures pass), but real-world
needs refinement before lefthook wiring (C5). Options for follow-up:
- Scope match to explicit «§0 cross-refs» table marker.
- Distinguish «current cross-ref» from «historical наследие mention»
by surrounding markup.
- Restrict regex to cross-ref tables (markdown | columns) only.
Until refined: C2 will be wired in C5 with caveat (WARN-only, or
disabled) to avoid blocking every commit on pre-existing 'наследие'
entries.
Extracted Tooling Прил. Н version via **Версия:** pattern (file-level
v8.3 wrapper at line 1 was misleading — Прил. Н is v2.17 at line 4).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Pure regex/JSON, 0 LLM calls. 4 Vitest tests GREEN. Per ADR-011 + spec §6.1.
Smoke run surfaces REAL drift (DONE_WITH_CONCERNS — plan B5 said «that's
a real signal, document, don't fix here»): 9 plugins in
~/.claude/settings.json enabledPlugins NOT formalized by exact
«name@source» string in Tooling Прил. Н:
- frontend-design@claude-plugins-official (informally as #30
«Frontend Design plugin»)
- 8× ToB plugins @trailofbits (differential-review, audit-context-
building, supply-chain-risk-auditor, insecure-defaults, sharp-
edges, static-analysis, variant-analysis, agentic-actions-auditor)
informally as #39 «Trail of Bits Skills»
This is naming-vocabulary mismatch (Tooling uses human-readable
names; settings.json uses machine names). Not architectural drift.
Resolution options for follow-up:
- Add machine names as «external_id» attribute to Tooling Прил. Н rows.
- Add tools/.l1-watcher-aliases.txt with accepted machine→human map.
Until resolved: C1 will FAIL on lefthook (C5 wiring) — addressed in
C5 by adding alias mechanism OR temporarily downgrade to WARN.
Also fixed CLI guard bug in observer-stop-hook.mjs (B3) and l1-watcher
— old guard `import.meta.url === \`file://\${argv[1]}\`` did not match
on Windows (file:/// triple-slash vs file:// double-slash + relative
argv[1]). New guard: argv[1].endsWith('/<filename>.mjs').
Weekly GH Actions cron (Mon 09:00 MSK) opens issue on drift.
Vitest config extended to ../tools/*.test.mjs with exclude for ruflo-*
and subagent-prompt-prefix tests (pre-existing, not part of brain
governance).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
HK1 pre-check passed in B4 (0cf1406): user-level Stop = agent-type
economy verifier (independent slot); project-level Stop was empty.
Added project-level Stop hook: command-type, 5s timeout, never
blocks (exit 0 on error per implementation a825700). Per Pravila
§16.2 + ADR-011.
Real-session smoke test deferred to Task D2 end-to-end smoke (semi-
manual — triggers real Claude Stop event).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Verified Stop event collision before B5 registration:
- User-level (~/.claude/settings.json): Stop hook = agent-type
Sonnet-4.6 economy compliance verifier (already wired in
6-component arch).
- Project-level (.claude/settings.json): Stop slot empty.
observer-stop-hook will register as command-type entry in
project-level Stop array. Independent slot from user-level agent;
no overwrite, no collision. Per Pravila ADR-010 HK1 hard-rule.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Hook contract: reads JSON ctx from stdin (Claude Code Stop-event),
builds episode with 5 mandatory fields including primary_rationale
(7 sub-fields per spec v1.1 §5.2.1), sanitizes via observer-pii-filter,
appends to docs/observer/episodes-YYYY-MM.jsonl. Never blocks
Stop-event (exit 0 on error).
8 Vitest tests verified GREEN (6 in appendEpisode + 2 in
buildEpisodeFromContext): append/append-existing/PII-filter/
missing-required/missing-rationale-field/routing_decision-preserved
+ buildEpisode 5-field extraction + user-rationale-preserved.
Vitest config for tools/ already covers via glob ../tools/observer-*.test.mjs
(extended in B2 commit 4616308).
Per Pravila §16.2 + ADR-011 + spec v1.1 §5.2.1 (factor analysis).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Used by Stop-hook before JSONL write. 6 Vitest cases including
idempotence and recursive object sanitization. Per Pravila §16.2 +
ADR-011 + spec §5.4.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Empty infrastructure per ADR-011 + Pravila §16.2. Hook + generators
wire up in subsequent tasks (B2 PII filter, B3 Stop-hook, B5 register
in settings.json, C4 STATUS generator).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
+ §0.1 row template (one-time, ADR-011 mandated).
+ Атрибуты block for phase-0 nodes #1-#9. #1 PostgreSQL MCP dormant
(replaced by #10 Boost in phase 1).
Per spec §4.1, plan Task A3 sub-batch 1. Tooling header v2.16
remains; final v2.17 bump after all 6 sub-batches.
NB: file-layout adaptation — phase-0 nodes #1-#9 live in §2 tables
(not §4.X subsections); Атрибуты blocks placed in new §2.4
subsection. Plan-template "§4.1..§4.9" referenced the abstract
node-index, not file headings; subsequent sub-batches will follow
same pattern (§3.5 for phase-1 nodes #10-#18, etc.).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Single SoT for task→node routing. Replaces implicit routing scattered
across Pravila/PSR_v1/Tooling/routing-off-phase.md. ADR-011.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Соответствует spec v1.1 (544c8f3). Изменения:
Task A1 (ADR-011 text inside plan):
- Decision #2 «Observer scope B» расширено: упоминание 5 mandatory
fields (включая primary_rationale 7 sub-fields) + routing_decision
events для цепочек + что это enables factor analysis.
Task B3 (observer-stop-hook.test.mjs + observer-stop-hook.mjs):
- REQUIRED_FIELDS расширен с 4 до 5 ('primary_rationale').
- Новая константа RATIONALE_FIELDS (7 полей) + validateRationale()
функция, вызываемая внутри appendEpisode после top-level validation.
- buildEpisodeFromContext возвращает primary_rationale (либо из ctx,
либо default с extracted hints из ctx.skill_id/triggers_matched/etc).
- Tests: было 5 → стало 8. Новые: «throws when primary_rationale
field missing», «persists routing_decision events with structured
fields», «preserves user-provided primary_rationale unchanged».
Все old fixtures обогащены primary_rationale: defaultRat().
Task B6 (aggregation-template.md):
- Новая большая секция «Factor analysis matrix (v1.1+)» с 5 осями
факторов + cross-tab factor×factor. Tables для каждой оси:
triggers_matched, candidates_dropped_because, boundaries_applied,
hard_floor.rules, task_classification.
Self-review:
- Spec coverage table +row для §5.2.1.
Связано: spec v1.1 (544c8f3), plan v1.0 (ca93cf7), spec v1.0 (dd5bded).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
User-requested перед запуском суб-агента: observer должен фиксировать
не только факт выбора узла, но и причину — чтобы был возможен
факторный анализ через /brain-retro.
Изменения §5.2:
- 4 обязательных поля → 5 (+primary_rationale на эпизод-уровне).
- Новое событие routing_decision в массиве events[] (1 на каждое
решение роутера в сессии; для цепочки из N — N событий).
- Новая под-секция §5.2.1 — структура 7 полей (step / node_chosen /
triggers_matched / candidates_considered / boundaries_applied /
hard_floor / task_classification). primary_rationale — копия
первого routing_decision для дешёвой агрегации без чтения events[].
- Полный JSON-пример эпизода с цепочкой из 2 узлов.
Изменения §5.5:
- /brain-retro aggregation расширен новой секцией «Факторная матрица»:
таблица «узел × фактор × частота» + cross-tab «фактор × фактор».
5 осей факторов: triggers / dropped_because / boundaries /
hard_floor.rules / task_classification.
Эффект: /brain-retro теперь может выдавать утверждения уровня «#55
выбрался против #53 по ADR-009 7 раз и по triggers-match 5 раз», а
не просто «#55 использован 12 раз». Это closes гэп факторного
анализа.
Header bump v1.0 → v1.1. ADR-011 текст в плане Task A1 будет
обновлён следующим коммитом (план amendment).
Связано: dd5bded (spec v1.0), ca93cf7 (plan v1.0).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Финальный code-review эпика: insertGetId log-строки был вне try → при
падении самого insertGetId (БД недоступна) finally не освобождал
Cache::lock → lock висел LOCK_TTL_SECONDS (600с), пропуская 2 следующих
запуска. Перенесён внутрь try; $logId инициализируется null, catch
guard'ит обращение к нему.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Резервный CSV-канал (Путь 2): отчёт поставщика «Запрос номеров» не
содержит vid -> CSV-recovered лиды имеют vid=NULL. UNIQUE-индекс
idx_supplier_leads_vid_unique сохранён (PostgreSQL NULL != NULL).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
iter8 (commit 9fcefa3) проставил 10 ruflo-узлам флаг
NODE_META.isolated=true, но это метаданные — рендер vis.js
флаг не читал, узлы рисовались обычным оранжевым цветом
группы ruflo. На карте изоляция была не видна.
Изоляция через group-level (переживает режимы карты —
теплокарту/фильтр, которые перезаписывают opacity/borderWidth,
но не color/shapeProperties):
- GROUPS.ruflo: оранжевый #ff8800 → серый #555555 +
shapeProperties.borderDashes [4,4] + приглушённый шрифт #8a8a8a
- легенда-фильтр: dot оранжевый → серый dashed, текст
«🌊 ruflo (оркестратор)» → «🔇 ruflo (изолирован 18.05)»
- hk_ruflo_queen: group 'hooks' → 'ruflo' (10-й изолированный
узел, был в hooks-кластере — теперь визуально в ruflo)
- CATEGORY_LABELS.ruflo: «оркестратор» → «изолирован»
Группа ruflo не опустела (все 9 её узлов изолированы) — фильтр
group:ruflo продолжает работать. NODE_META.isolated флаги
не трогались (data-слой корректен с iter8).
Верификация: JS-синтаксис проверен (vm.Script parse OK) +
stylelint GREEN (color-hex-length fix #888→#888888). Визуальный
рендер в браузере НЕ проверен — Playwright-профиль занят
параллельной Claude-сессией (тот самый mcp_pw↔sk_parallel
same-dir case). shapeProperties — документированная vis.js
group-опция, риск низкий.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
7 задач TDD: миграция vid->nullable, rework SupplierCsvParser +
CsvReconcileJob, +3 метода SupplierPortalClient, scheduler 30 мин,
API + UI-экран «Интеграция с поставщиком».
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Резервный CSV-канал импорта лидов от crm.bp-gr.ru: страховка на случай
обрыва webhook. Сверка отчёта поставщика «Запрос номеров» (CSV 3 колонки
Name;Tag;Phone) каждые 30 мин + кнопка вручную; дедуп по phone+project;
recovery пропущенных лидов; drift-детект падения webhook.
Дизайн утверждён заказчиком. Ключевые решения: vid → nullable (CSV не
даёт vid), окно 2 кал. дня, rework SupplierCsvParser/CsvReconcileJob под
реальный async-флоу заказа отчёта.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Поставщик crm.bp-gr.ru шлёт B1-проекты, чьё имя — свободный текст со
встроенным URL/доменом (B1_заявка carmoney.ru/, B1_Платежи
cabinet.caranga.ru/login, B1_krk-finance.ru/cabinet/auth). Старый
anchored-regex требовал, чтобы вся строка после B1_ была чистым доменом;
такой rest не матчил — классификация sms — B1+sms — DomainException
(chk_supplier_projects_b1_not_for_sms) — 21 реальный лид застрял с error,
0 сделок.
Fix: после двух anchored-проверок (call/site) — fallback-извлечение
домена с латинским TLD из любой позиции строки — signal_type=site,
identifier = извлечённый домен. Реальные sms-имена (B1_TINKOFF) без
точки-домена остаются sms — существующий B1+SMS-тест не затронут.
3 параметризованных теста (carmoney/caranga/krk) + регрессия:
RouteSupplierLeadJobTest 12/12, Supplier+Integration+Webhook 61/61.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
UX-request 18.05.2026 (п.9):
- ProjectDetailsDrawer (правая панель на /projects) теперь редактирует
signal_identifier для site (домен) и call (телефон 7\d{10}); для sms —
sms_senders+sms_keyword (как раньше).
- Поле «Источник» отображается **только** в карточке проекта (read-only
в drawer сделки на /deals — Task 2 закрыл).
Backend:
- UpdateProjectRequest: condition-based валидация по signal_type из БД
(site domain regex, call 11-digit 7\d{10}; sms — без новых правил)
- ProjectService::update: убран signal_identifier из silent-drop;
$needsResync расширен на signal_identifier → SyncSupplierProjectJob
signal_type остаётся immutable (менять тип проекта — отдельная задача).
Larastan baseline bumped (ProjectsUpdateTest: actingAs 8→12 для 4 новых тестов).
Pest tests/Feature/Plan5/Projects/ProjectsUpdateTest 12/12.
Vitest 33 passes на Project-spec'ах. Build 2.03s.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
UX-request 18.05.2026 (п.8):
- Сайт: «Источник — домен сайта-«донора», с которого приходят лиды»
- Звонок: «Источник — телефонный номер «донора», на который звонят клиенты»
- СМС: «Источник — отправитель SMS и (опционально) ключевое слово в тексте»
Подпись text-caption text-medium-emphasis, выше существующего label поля.
Один и тот же NewProjectDialog используется и для create, и для edit.
NewProjectDialog.spec.ts 5/2sk/0 — без регрессий. Build 1.96s.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Поставщик crm.bp префиксует имена проектов признаком канала-провайдера
(B1_/B2_/B3_ — три базы лидов). В UI Лидерры префикс — шум: пользователю
интересен сам проект, не канал.
Трансформация display-only — данные в БД не трогаем, фильтрация идёт по
project_id (не name).
Утилита: app/resources/js/composables/projectName.ts → stripChannelPrefix.
Регэксп ^B[123]_ case-insensitive; null/undefined/'' → ''.
Применено в 4 точках:
- DealsTable «Источник» (item.project)
- DealsFilters «Проект» dropdown (через computed-маппинг в DealsView)
- KanbanCard карточка
- DealDetailBody параметры панели
Тесты: 8 unit-тестов на утилиту (B1/B2/B3 case-insensitive, не трогать
B0/B4/Bx, не трогать префикс в середине строки, null/undefined/''),
38/38 на затронутых компонентах, 868/3sk/0 full Vitest, build 2.62s.
Smoke /deals: 20 строк, ни одна не начинается с B1_/B2_/B3_ (был
«B1_73912557675 [35]», стал «73912557675 [35]»; «B3_krk-finance.ru/...»
→ «krk-finance.ru/...»). Скриншот deals-no-bprefix-2026-05-18.png.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Ветка ребейзнута на parallel-sessions §15 — Pravila v1.27 и CLAUDE.md
v2.14 параллельно заняты §15-эпиком, перенумеровано Pravila→v1.28 /
CLAUDE.md→v2.15. Sync cross-refs: Tooling §0+§13 footer, PSR_v1 §0
entry, automation-graph rule-labels (pravila/claude_md узлы),
+rebase-девиация note в plan. Tooling v2.14 / PSR_v1 v3.13 — без
изменений (§15 их не трогал).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Регистрирует tools/subagent-prompt-prefix.mjs как PreToolUse-хук
matcher:'Task'. JSON валиден (node -e JSON.parse OK).
Хук становится LIVE для всех будущих Task-инвокаций — auto-inject
SUBAGENT GIT-SAFETY HEADER (cwd/branch/HEAD/worktree-root + rules 1-5)
per Pravila §15.1.
End-to-end smoke verified at next Task dispatch (Task 7 плана —
wrapper-skill subagent-driven-development).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Previous test 5 stripped PATH entirely, which kills node.exe spawn resolution
on Windows (CreateProcess needs PATH to find node). Changed to set PATH to
node's own directory only — node spawns fine, git is not in node-dir → ENOENT
→ hook fail-opens per spec §4.5.
All 5 tests now pass cross-platform.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Per Pravila §15.1 — инжектит cwd/branch/HEAD/worktree-root + правила
поведения в каждый Task-prompt. FAIL-OPEN на любой ошибке (git
не в PATH, malformed stdin, non-Task tools).
Все 5 тестов из subagent-prompt-prefix.test.mjs PASS.
Регистрация в .claude/settings.json — Task 6 плана.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5 тестов для Task git-safety inject хука:
- inject SUBAGENT GIT-SAFETY HEADER в Task-prompt
- inject real cwd/branch/HEAD/worktree-root
- passes through non-Task tools
- fail-open on malformed stdin
- fail-open when git unavailable
Tests FAIL — hook implementation в следующем коммите (TDD green-phase).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Создаём docs/sessions/ — координация per Pravila §15.2 (claim/check/release
жизненный цикл, конфликт-резолюция). CURRENT.md содержит текущую сессию
parallel-sessions-coordination + retro-claim записи для существующих
активных worktrees (16 user-sessions на 2026-05-18; 2 locked agent-* worktrees
исключены — не user-сессии).
Backfill scope/version-claims заполнен best-effort; активные сессии
обновят свой блок при возобновлении работы.
+cspell-words: парсится (валидная транслитерация).
Spec: docs/superpowers/specs/2026-05-18-parallel-sessions-coordination-design.md
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Deals page redesign: design spec + implementation plan (Phase A page redesign,
Phase B 14->5 status funnel) + v8 HTML mockups (variants comparison + final).
AppSidebar: remove Импорт данных / Отчёты nav links (routes stay reachable by
direct URL); AppLayout.spec updated to 6 nav items. stylelint --fix on mockups;
cspell-words += deals-redesign terms.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
docs(a3): cspell-words.txt +ребейз-family
ребейз/ребейзнута/ребейзом — слова из CLAUDE.md §6/§9 и spec §7
(описание ребейза feat/a3 на origin/main). Единственные реально новые
термины A3-нормативки по cspell-прогону добавленных строк.
Task 10 плана A3 integration-tooling.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@
docs(a3): PSR_v1 v3.9 — R10.1 Блок 3 +openapi-mcp (integration-tooling)
R10.1 Блок 3 (MCP-серверы) +1 строка openapi-mcp-server — категория
integration-tooling, off-phase, раздел A3. Не UI → вне R6/R14.
Tooling §4.22 #47. Версия v3.8→v3.9.
Task 7 плана A3 integration-tooling.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@
The 8-task plan executed for the A4 epic, with the post-flight Plan Correction block (FM2 defer, #44-46 numbering, ADR-006, knowledge-work-plugins marketplace, /plugin unavailable in VSCode-extension env).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The 'design' plugin lives in anthropics/knowledge-work-plugins (same marketplace as #42 product-management), not claude-plugins-official (which carries only frontend-design). Verified post-reload against the marketplace manifest. Pre-push fixup of 621498a's own error - v2.8/v3.8/v2.8 unchanged. Tooling 4.21 also completes the capability list (+Design System Management, +Dev Handoff).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
docs/architecture/c4-component-layers.md — the Level-3 layer
dependency graph generated by `deptrac analyse --formatter=mermaidjs`
(code-derived, drift-proof). Closes the A6 «C4 drift» gap at the
component level. README diagram index + regenerate note updated.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Job 10 runs `deptrac analyse` (root: app/) when staged app/**/*.php
changes — the layer-dependency gate. Red-green verified: a
Model→Service dependency is flagged (DependsOnDisallowedLayer,
exit 1); a clean tree exits 0. app/.gitignore += /.deptrac.cache.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
app/deptrac.yaml — 13 layers (Controller/Service/Model/Job/…),
conservative ruleset enforcing inward/upward-violating directions.
First `deptrac analyse`: 0 violations / 481 allowed / 977 uncovered
— the codebase already conforms, so no baseline file is needed.
ADR-005 records the decision.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
9-task plan closing the 4 open A6 architecture-fitness gaps
(conformance, layer-direction, C4 drift, active design) via
deptrac as a lefthook job-10 layer-dependency gate. + cspell vocab.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
C1: ProjectResource не возвращал regions → edit-диалог/drawer затирали
сохранённые регионы при сохранении. +поле в toArray().
C2: +integration-тест outbound regions[] через полный SyncSupplierProjectsJob::handle().
I1: расскип NewProjectDialog payload-теста (regions в POST).
I2: assert data.regions в ProjectsStore/UpdateTest (ловит C1 на backend-уровне).
I4: docblock — bulkUpdateRegions legacy (region_mask, не влияет на outbound до Plan 6.5).
M1: CHANGELOG v8.22 — исправлен неверный пример регионов (Москва=82).
Регрессия: Pest 905/902/3sk/0, Vitest 104f/884/3sk/0.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The D3 plan still describes Security Guidance #40 as warn-only (the pre-correction belief). Plan body kept as a historical snapshot; added a one-line NB pointing to the v2.5 correction (Tooling §4.15 / ADR-003 / CLAUDE.md).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
SG #40 was characterised across all D3 docs as warn-only / does not block. Verified end-to-end: security_reminder_hook.py does sys.exit(2) — a BLOCKING PreToolUse hook (one-time speed-bump per file+rule per session, the retry passes).
SG2: on this Windows host the bundled hooks.json hardcodes python3, absent from PATH — the hook never spawned (inert). Fixed with a python3.exe shim in the Python install dir (env-only, not in repo).
Normative sync: Tooling v2.5, PSR_v1 v3.5, Pravila v1.19, CLAUDE.md v2.5; ADR-003 amended; automation-graph sec_guidance nd(). Tool counts unchanged (40 positions).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The 9-task plan for the adr-kit / mermaid-skill / architecture-patterns
integration. Committed alongside the work it produced (commits b15a94a..93ac262).
cspell-words.txt: +inertiajs +Sev (plan-file vocabulary).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
adr-judge crashed (UnicodeEncodeError: surrogate '\udc98') when the staged diff contained non-ASCII content: Python reads piped stdin with the Windows cp1251 console codepage, not UTF-8, so a Cyrillic diff mis-decodes into surrogates and dies at diff_text.encode('utf-8'). '-X utf8' forces Python UTF-8 mode. Task 5's red-test probe was ASCII, so the crash went unseen until Task 6's Cyrillic docs/architecture files. adr-judge's file reads already use explicit encoding='utf-8'; only stdin was affected.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
adr-judge v0.13.1 vendored from the adr-kit plugin (MIT) -> tools/adr-judge.py (819 lines, Python stdlib only). lefthook pre-commit job 9 runs 'git diff --cached --unified=0 | python tools/adr-judge.py --diff - --adr-dir docs/adr/'.
AK6 resolved: the --llm flag is NOT passed, so adr-judge runs declarative regex only — no Claude Sonnet call, zero economy cost. adr-kit's own git-hook template passes --llm; we deliberately do not, and lefthook keeps sole ownership of .git/hooks (AK1).
Verified: red test — staged @inertiajs/vue3 import in app/resources/js/ blocked with VIOLATION citing ADR-001 line 1, lefthook exit 1. Green test — clean diff, 9/9 jobs pass.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Three seed ADRs to the adr-kit 7-section template: ADR-000 (process + docs/adr vs registry vs docs/architecture boundary), ADR-001 (Vue 3 + Vuetify 3 stack, with an Enforcement block forbidding Inertia/React/framer-motion/Tailwind imports), ADR-002 (PostgreSQL RLS multi-tenancy, documentation-only).
adr-lint: 3/3 PASS strictly (completeness + consistency). markdownlint 0 errors. .claude/adr-kit-guide.md vendored from the plugin (replaces what adr-kit:init would write to CLAUDE.md — AK2). cspell glossary += ADR/rvdbreemen/secondsky/NNN/MMM. init/install-hooks NOT run.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
markdownlint-cli2 --fix: blanks-around-lists/fences в плане 5B.
0 errors. Pre-existing 26 ошибок в планах Sprint 4/5A — вне scope.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
План 6 задач портал-аудита Sprint 5B. T2 NAV_ITEMS поправлен 7→8
(добавлен «Импорт данных» /import — сверено с origin/main-сайдбаром).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Code-quality review T1: stale JSDoc «Counts — mock» теперь ложный
(count live из API); +поясняющий комментарий к null→undefined цепочке.
Comment-only, 0 изменений поведения. Vitest 6/6 green.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Слой WISHLIST: панель отложенных хотелок развития мозга/портала + кнопка-легенда «💡 Хотелки» в нижней легенде. Засеяно 4 хотелками раздела E8: K7-spike, мост claude-mem→ReasoningBank, claude-mem #1, двухуровневый ремонтник. Аддитивно — режим легенды наравне с «Разделы»; счётчики узлов/рёбер не меняются.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Final review (🟢 low): SPA-маршрут /import работал через Route::fallback,
но все остальные app-маршруты перечислены явно в Route::view-блоке
(CLAUDE.md документирует явный список как намеренный паттерн — catch-all
перехватывал бы _test/* runtime-роуты Pest). /import добавлен в список
для консистентности и устойчивости.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Final review нашёл: HistoricalImportService::loadStatusOverrides и
persistUnknownStatuses запрашивали import_unknown_statuses без явного
where(tenant_id), полагаясь на RLS через SET LOCAL. Но queue worker на prod
работает под crm_supplier_worker — BYPASSRLS-роль (00_create_roles.sql §5),
SET LOCAL не фильтрует → cross-tenant утечка: импорт тенанта A мог подхватить
resolved-маппинг тенанта B и инкрементировать его occurrences.
Добавлен явный where(tenant_id) в обе выборки (конвенция defense-in-depth
00_create_roles.sql:64 — WHERE-фильтры обязательны под BYPASSRLS). +тест
cross-tenant изоляции (red-green verified: без фикса 'Архив' тенанта A
получал status 'closed' из чужого маппинга).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Code-review Task 10 (🟡): магическое число 2000 (интервал polling'а) вынесено
в именованную константу POLL_INTERVAL_MS — паттерн файла (как в DashboardView).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
TDD: spec (3 tests) first, then component.
ImportView.vue: upload form + polling + history table + unknown-statuses banner.
Uses api/imports (uploadImport/listImports/getImport/getUnknownStatuses).
setInterval callback wrapped in named async fn (pollOnce) — no eslint-disable needed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Code-review Task 9 (🟡): добавлен тест защиты show() — пользователь одного
тенанта получает 403 при запросе import_log другого тенанта (покрывает
abort_if defense-in-depth в ImportController::show). phpstan-baseline
регенерирован — инкремент count ложного TestCall-срабатывания (квирк 25).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ShouldQueue-job: читает CSV через Storage::disk('local'), парсит через
CsvLeadsParser, импортирует через HistoricalImportService (4 аргумента),
обновляет import_log (pending→processing→done|failed), шлёт
ImportCompletedNotification. RLS через SET LOCAL в каждой транзакции.
tries=1 (идемпотентность на уровне строк, повторный прогон искажает
счётчики — авто-ретрай отключён). Larastan: 0 новых ошибок.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Code-review Task 6 (non-blocking 🟡): HistoricalImportService объявлен final
(симметрия с ImportResult, утилитарный сервис без наследования). Ключ ошибки
upsert'а переименован 'line' → 'source_crm_id' — поле хранит идентификатор из
исходной CRM, а не файловую строку (в отличие от CsvParseResult::errors).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Реализован HistoricalImportService с ImportResult DTO и 7 feature-тестами
(TDD). Идемпотентный upsert через pg_advisory_xact_lock + webhook_dedup_keys;
создание партиций через MonthlyPartitionManager; напоминания; unknown-статусы
с tenant-переопределениями; dry_run режим; historical_import tx без списания
баланса. Попутный fix CarbonImmutable-петли в MonthlyPartitionManager::ensureRange.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Code-review Task 5 (non-blocking 🟡): CsvLeadsParser объявлен final (симметрия
с DTO ParsedLeadRow/CsvParseResult, утилитарный класс без наследования);
строка ошибки про число колонок использует self::EXPECTED_COLUMNS вместо
литерала 9.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Парсер CSV-выгрузки лидов crm.bp-gr.ru (ТЗ §6.2/§6.3): срезает UTF-8 BOM,
разбирает строки через str_getcsv, валидирует телефон (7XXXXXXXXXX) и даты
(Y/m/d H:i:s), срезает префикс B[123]_ из названия проекта. Невалидные
строки не роняют парсинг — собираются в errors[] с абсолютным номером строки.
Тесты: 5/5 (unit, без DB).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Выносит DDL-логику создания месячных RANGE-партиций из команды
PartitionsCreateMonths в переиспользуемый сервис MonthlyPartitionManager.
Сервис используется командой (DRY) и будет использован HistoricalImportService
для партиций под исторические даты CSV.
- MonthlyPartitionManager::ensureRange(table, from, to) — гарантирует партиции
под диапазон дат, идемпотентно; отвергает незарегистрированные таблицы
- MonthlyPartitionManager::ensureMonth(table, monthStart) — одна партиция
- PartitionsCreateMonths рефакторена: убраны PARTITIONED_TABLES, partitionExists(),
use DB; inject MonthlyPartitionManager через handle()
- Test: MonthlyPartitionManagerTest (3 теста, DatabaseTransactions — DDL откат)
- Regression: PartitionsCreateMonthsTest (4 теста) — зелёный, поведение не изменилось
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Code-review Task 1: явный per-table GRANT-блок для import_unknown_statuses
использовал несуществующие роли (crm_app_admin / crm_readonly). Реальные роли —
crm_app_user / crm_admin_user / crm_migrator / crm_audit_writer /
crm_supplier_worker (db/00_create_roles.sql). Блок удалён целиком из
db/02_grants.sql и db/schema.sql: import_unknown_statuses — обычная
tenant-scoped таблица, покрыта umbrella GRANT ... ON ALL TABLES +
ALTER DEFAULT PRIVILEGES (как import_log), явный per-table grant не нужен.
ImportSchemaTest: UNIQUE-тест усилен — проверяет состав колонок
(status_ru, tenant_id), а не только наличие constraint'а типа 'u'.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
+1 раздел в блок E «Мета и управление». Итого 40 разделов
(13 наполнены / 27 пусты). E8 — пустой каркас под будущий playbook.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
39 разделов деятельности Лидерры (5 блоков A–E) как классификация:
все 83 узла распределены по разделам — 13 наполнены, 26 пусты
(пустые — бизнес-домены, под которые в карте dev-автоматики узлов
ещё нет). Кнопка-панель «📂 Разделы» + строка «Раздел» в Паспорте
узла. Топология карты (83/90/11) и радиальный layout без изменений.
Основа будущего «мозга»: 1 раздел = 1 playbook.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Pre-existing баг: 5×../ перелетал repo-root на 2 уровня. Поймана pre-push lychee реколлажа. Корректный путь от docs/superpowers/specs/ до repo-root CLAUDE.md — 3×../
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
cspell.json useGitignore:true заставлял cspell игнорировать все файлы worktree, расположенного под gitignored .claude/worktrees/ (Files checked: 0 — фейковый green). Staged-файлы по определению tracked, потому --no-gitignore для pre-commit cspell безопасен и чинит worktree-коммиты.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
B4 + B5 реализованы и закрыты; B1 «Напоминания в сайдбар» откатан как
конфликтующий с прежним решением заказчика «sidebar cleanup» (5c8ad27).
Отмечено в §3 расписании, §4 таблице B и §8 approval log.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Дописана §11: 6 скоростных правил (блок A 5 пунктов + блок B п.3) внесены секцией СКОРОСТЬ в LEVELS[5] хуков; B4 (замер latency хуков) задокументирован как закрытый одноразовый bench. §5.1/§5.2 актуализированы под текущие хуки, §2 формула расширена, статус-шапка → Реализован.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Откат a55ac9d. Audit B1 предлагал вернуть «Напоминания» в сайдбар, но
пункт был намеренно убран по требованию заказчика (commit 5c8ad27
«sidebar cleanup»; тест AppLayout.spec.ts фиксирует «Напоминания убраны
по требованию заказчика»). Решение заказчика 2026-05-16: B1 → won't-do,
пункт остаётся убранным. Восстанавливает зелёный AppLayout.spec.ts.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
SupplierPortalClient::loadSession, RefreshSupplierSessionJob, CsvReconcileJob and RouteSupplierLeadJob hardcode Cache::store('redis'), bypassing phpunit.xml's CACHE_STORE=array. Under pest --parallel every worker shares the same Memurai instance and the global supplier:session key, so one worker's afterEach forget()/flush() races another worker's mid-test loadSession() -- deterministic 1-2 failures in the tests/Feature/Supplier/ subdir-only run (quirk 72).
TestCase::setUp() repoints the redis cache store at the in-process array driver: each parallel worker gets a hermetic, worker-local cache. Production keeps the real redis driver -- the override only runs under APP_ENV=testing. New RedisCacheStoreIsolationTest guards the invariant.
Verified: tests/Feature/Supplier/ --parallel 6/6 runs 43/43 (was 42/43 +1 error); tests/Unit/Supplier/ 3/3 runs 38/38; full pest --parallel 794/791/3sk/0; Pint + Larastan clean.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
pest --parallel emits a single JSON line {"tool":"pest","tests":N,"passed":N,"skipped":N,...}
instead of human-readable text; the old regex-only parser returned 0/0/0sk/0 for every
parallel run. Added JSON-first branch with regex fallback; 3 new unit tests cover the
JSON path (passed+skipped, with failures, no skipped field).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Уровень «экономия 5%» = «0% без избыточности»: то же качество, что 0%,
вырезаны 6 пунктов дублирующей/бесполезной работы (re-read CLAUDE.md,
тесты-после-каждой-правки, gitleaks-full-history per-commit, Stop-верификатор,
авто-гейты brainstorming/plan-mode -> §12.2-floor). Уровень 0% не меняется.
cspell-words.txt: +коммитятся (валидная форма семейства коммит*).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Both tools check RLS compliance; the boundary "когда какой" was
undocumented (tracked as a RED conflict on the automation graph).
- .claude/skills/rls-check/SKILL.md: +section "Граница с агентом
rls-reviewer", +bullet in "Не использовать когда", +clause in
the frontmatter description.
- .claude/agents/rls-reviewer.md: +mirrored section "Граница со
скилом /rls-check", +bullet in "Out of scope", +clause in
the description.
- docs/automation-graph.html: conflict sk_rls<->ag_rls recolored
RED->GREEN (CONFLICT edge + both nd() node entries + EDGE_META).
- cspell-words.txt: +1 pre-existing word surfaced by the cspell
full-file scan of the now-staged SKILL.md.
Rule: one named table -> /rls-check; diff/branch/PR -> rls-reviewer.
The smoke test stays skill-only by design (running Pest in a review
subagent is slow and hits --parallel quirks 72/77).
Spec: docs/superpowers/specs/2026-05-16-rls-tooling-boundary-design.md
Plan: docs/superpowers/plans/2026-05-16-rls-tooling-boundary.md
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
A missing cmd-based tool on Windows exits 1 with an "is not recognized"
message, not POSIX exit 127. runCheck now also matches that message so a
missing composer/npm is classified SKIPPED (verdict RED-INCOMPLETE) per
spec §8, instead of a plain failure. Code-review follow-up for Task 7.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Code-quality review fixups: Number.isFinite-guard в amountError/canSubmit
(очищенное number-поле не должно включать кнопку); watch(model) сбрасывает
amount/errorMsg при открытии (паттерн ReminderDialog, нет префилла/race);
комментарий про намеренный refetch в onTopupSuccess; flushPromises в spec.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
8-task plan for the rls-check skill <-> rls-reviewer agent boundary:
mirrored "Граница..." sections in both tool files, conflict recolor
RED->GREEN on the automation graph (4 spots), lint sweep, Playwright
visual smoke, one atomic commit, memory sync.
Spec: docs/superpowers/specs/2026-05-16-rls-tooling-boundary-design.md
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
4-task plan for iter6 of docs/automation-graph.html: «Паспорт узла»
legend section (since/changed/uses) for all 83 nodes + 2 footer toggle
buttons (usage heatmap, duplicate highlight). NODE_META (83 records) and
DUPLICATE_GROUPS (6 pairs D1-D5/D7) carry factual values derived from
76 session transcripts (window 09-16.05.2026) + git history; method and
raw outputs in Appendix A. cspell-words.txt += pcreator, pvalid.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Code-quality review fixups: тест на :disabled PDF-кнопки по has_pdf
(spec-mandated поведение без покрытия); doc-комментарий billingFormatters
дополнен InvoicesTable в списке потребителей.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Дизайн-спек устранения конфликта 🔴 RED #1 карты автоматизации:
скил /rls-check и агент rls-reviewer оба проверяют RLS без чёткой
границы «когда какой».
Решение (Подход 1 — асимметрия как граница): оставить оба, прописать
регламент. Скил — одна названная таблица + живой дымовой тест;
агент — diff/ветка/PR, только 7 статических проверок. Дымовой тест
намеренно вне агента (Pest в ревью-субагенте медленный + задевает
квирки 72/77).
Затрагивает только проектно-локальные файлы инструментов + карту —
0 правок нормативки (Pravila/CLAUDE.md/PSR_v1/Tooling).
cspell-words.txt: +скиле +скилом (падежные формы термина «скил»).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Code-quality review fixups: loadWallet() catch-блок сбрасывает wallet в
null (нет ложного рендера устаревших данных при неудачном повторе);
тест на кнопку «Повторить» (re-fetch + переход в success-состояние).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
api/billing.ts (getWallet) + BillingView тянет GET /api/billing/wallet
на mount (шапка + BalanceCard, loading/error-state). BalanceCard на
реальные props с nullable-тарифом. featureLabel для feature-слагов.
Sprint 2 Plan C, audit E3 (frontend pt1).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Spec §10 claimed run.mjs needs no unit harness, on the false premise that tools/*.mjs have no tests. In fact all 3 tools/*.mjs have a co-located .test.mjs (node:test). Amended §2/§3/§4/§10 + header note: run.mjs is split into exported pure functions (parsers, verdict, canonical-line, platform fork) + orchestrator, with a co-located run.test.mjs (node:test, ruflo-queen-hook.test.mjs pattern) — pure functions unit-tested, main subprocess-tested.
Aligns the spec with the economy-0% TDD mandate and the project tools/*.mjs convention before writing the implementation plan.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Code-quality review fixups: runway_days клампится в 0 при отрицательном
балансе (overdrawn-тенант не должен показывать «−N дней»); (int)-каст в
wallet() для консистентности; усилены assertJsonPath на type-фильтре.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Brainstorming-phase design for custom skill #1 from claude-automation-recommender: a /regression skill packaging the project regression sweep (Pest --parallel, Vitest, Larastan, vue-tsc, lint/format, lychee, gitleaks) into one invocation — two tiers (quick/full), bundled .mjs orchestrator, canonical status line, GREEN/RED exit-code verdict.
Q1-Q4 design forks approved via brainstorming; spec self-review passed. cspell-words.txt: +6 project glossary transliterations introduced by the spec. Next: superpowers:writing-plans for the implementation plan.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Code-quality review fixups: документирующий комментарий про безопасность
Eloquent save() для bcmath-строки (расхождение с LedgerService raw-update);
cross-tenant isolation тест на /api/billing/topup; balance_rub_after в
assertDatabaseHas.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
BillingTopupService кредитует tenants.balance_rub (bcmath) и пишет
append-only строку balance_transactions(type='topup'). BillingController
+ route POST /api/billing/topup под [auth:sanctum, tenant]. MVP-stub:
без платёжного шлюза (ЮKassa — post-Б-1).
Sprint 2 Plan C, audit E1 (backend).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
5-task план реализации audit-эпиков E1 (TopupDialog + POST
/api/billing/topup stub) и E3 (BillingView Overview на real API:
wallet/transactions/invoices). Backend: BillingController +
BillingTopupService + TariffPlan. Frontend: api/billing.ts + 4
компонента биллинга с mock на real API.
Sprint 2 Plan C. Источник: docs/superpowers/specs/2026-05-15-portal-audit-design.md.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
План реализации iter5 поверх spec efd588f: 2 задачи (реколлаж кластера
ruflo в automation-graph.html одним атомарным коммитом + синхронизация
memory). Полное литеральное содержание узлов/рёбер/деталей, верификация
через grep + visual smoke. +2 слова в cspell-words.txt (арг, греп).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Code-quality review of Task 5: adds tests for the loadApiKey/loadWebhook
catch branches (apiKeyError/webhookError -> error v-alert) and changes
the Copy-button disabled check to the idiomatic falsy form.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Audit D2/D3/D4/D5: all four ApiTab buttons were handler-less and the
fields were hardcoded. Adds api/apiKeys.ts + api/webhooks.ts modules and
rewires ApiTab: loads the api-key prefix + webhook settings on mount;
Copy -> clipboard + snackbar; Regenerate -> confirm dialog -> POST
regenerate (full key shown once); Save Webhook -> PUT webhook-settings;
Test Webhook -> POST test with the result in a snackbar.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Code-quality review of Task 4: adds a cross-tenant isolation test
(verifies the where(tenant_id) guard, matching ApiKeyControllerTest)
and a test()-endpoint failure-path test (HTTP 500 -> ok=false). Drops
the @return docblock from OutboundWebhookSubscriptionFactory for
consistency with ApiKeyFactory, eliminating a baseline entry at source.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Audit J5/D4/D5: the outbound_webhook_subscriptions table existed in
schema but had zero code. Adds the OutboundWebhookSubscription model +
factory and WebhookSettingsController with GET/PUT
/api/tenants/me/webhook-settings (one subscription per tenant; secret
generated + returned once on creation, bcrypt-hashed) and POST
/api/webhooks/test (unsigned connectivity check — HMAC-signed event
delivery is a separate post-MVP epic). Tenant-scoped via auth:sanctum +
tenant middleware.
phpstan-baseline.neon: additive-only entries for new test file
(Pest\PendingCalls\TestCall false-positives — documented project pattern)
and OutboundWebhookSubscriptionFactory method.childReturnType (same
pattern as ProjectFactory/TenantFactory/UserFactory already in baseline).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Code-quality review of Task 3: index() filtered by is_active only —
an expired-but-active key would be listed as valid. Adds an
expires_at > now() filter plus a test. Cannot occur today (regenerate
is the only write path, always +1 year) but is the correct semantic
contract for an «active key» listing.
phpstan-baseline.neon: count bumps only for ApiKeyControllerTest.php
($tenant 5→7, $user 3→5, getJson 3→4).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Audit J5/D3: the api_keys table existed in schema but had zero code.
Adds the ApiKey model + factory, and ApiKeyController with GET
/api/api-keys (list active keys, key_hash hidden) and POST
/api/api-keys/regenerate (deactivate prior + create new, full key
returned once, bcrypt-hashed in DB). Tenant-scoped via auth:sanctum +
tenant middleware (RLS on api_keys). phpstan-baseline.neon updated for
Pest PendingCalls false-positives in the new test file; also removes
8 pre-existing stale ignore.unmatched entries (properties now resolved
by existing @mixin IdeHelper* docblocks — confirmed pre-existing via
git stash test before Task 3 changes).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Code-quality review of Task 2: documents why ProfileTab needs no
watch-resync of auth.user (router beforeEach awaits fetchMe before
requiresAuth navigation); tightens the save-error test to assert the
exact fallback message instead of mere truthiness.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Audit D1: ProfileTab fields were hardcoded refs and the Save button had
no handler. Rewired to the auth store + a new api/auth updateProfile()
calling PATCH /api/auth/me. Single «Полное имя» field split into Имя +
Фамилия (matches users.first_name/last_name); decorative «Роль» field
removed (no such column). AuthUser type gains phone + timezone.
SettingsView.spec.ts updated: «Полное имя» assertion changed to check
for «Имя» and «Фамилия» (collateral fix for the intentional field split).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Code-quality review of Task 1: first_name had a 422 test but last_name
(identical required rule) did not. Adds the symmetric test.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
SyncSupplierProjectsJob:77 has a time-budget guard that breaks the
sync loop after 20:55 Europe/Moscow. Five of the eight tests in
SyncSupplierProjectsJobTest omitted Carbon::setTestNow(), so they
inherited real wall-clock time and silently failed (job no-ops)
every evening after 20:55 MSK -- a latent test bug since dedaae5
(Plan 3), mis-attributed to a Redis race (quirk 72) in earlier audits.
Pins beforeEach to a fixed pre-cutoff clock; the job code is correct
and unchanged. Verified: 8/8 in isolation, full suite back to green.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Audit J6: ProfileTab needs a full-profile update endpoint. Adds
AuthController::updateProfile (first_name/last_name/phone/timezone),
routed in the existing /api/auth auth:sanctum group; mirrors the
sibling updateNotificationPreferences. userResource() now also returns
phone + timezone so the GET /me round-trip carries them.
phpstan-baseline.neon updated for Pest PendingCalls false positives
in the new test file (same pattern as all other Feature test files).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Plan B of the Sprint 2 split — the Settings subsystem, 5 atomic TDD
tasks: PATCH /api/auth/me profile endpoint (J6); ProfileTab rewired to
real API (D1); ApiKey model + api-keys endpoints (J5/D3); outbound
webhook settings endpoints (J5/D4/D5); ApiTab full wiring (D2-D5).
Schema delta = 0 — api_keys + outbound_webhook_subscriptions tables
already exist in schema.sql.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Code-quality review of the legal stub pages: the always-present
informational v-alert defaulted to role=alert (assertive live-region) —
changed to role=note for a static advisory (WCAG 2.1 AA). Trimmed
cosmetic whitespace inside the back-link element.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Audit A7: the «Оферта» / «Политика» links in the AuthLayout footer were
raw <a href> pointing at unrouted paths -> 404 via the SPA catch-all.
Adds a single DRY LegalDocView served by /legal/:doc(offer|privacy),
rendering an honest «document being finalized» stub (real legal text
needs юр. редактура — реестр K3 / blocker Б-1). Footer links upgraded
to <RouterLink> for SPA navigation. Also refreshes two stale auth-layout
doc-comments left by the /recovery removal (review M1).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Audit A2/A3: RecoveryCodesView (route /recovery) had a TODO no-op
continue handler and 8 hardcoded mock codes. Recon found the page is
orphaned — nothing in the UI navigates to /recovery. The real 2FA
recovery-codes flow lives entirely in Settings -> Безопасность
(TwoFactorCard setup wizard + RecoveryCodesCard regeneration), both
already wired to the real API. Per user decision (2026-05-15) the
orphan is deleted rather than polished.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Удаление docs/automation-graph-ruflo.html (automation-graph iter4, d18b60f)
оставило битую markdown-ссылку в §«Связано». Конвертирована в backtick-спан
(как упоминания того же форка в CLAUDE.md) + нота «влит и удалён» —
исторический факт сохранён, pre-push lychee проходит.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Records the key divergence found during subagent-driven execution: the
H7 fix needed onnxruntime-node dedupe in addition to the getBridge patch
(two incompatible onnxruntime-node versions => DLL collision). Documents
3 residual ruflo-alpha quirks and the post-ruflo-update re-apply step.
cspell-words.txt +dlopen (ERR_DLOPEN_FAILED token).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Wire tools/ruflo-recall-hook.mjs into .claude/settings.json so ruflo
memory recall is injected per prompt. Project-scoped, fail-open.
Absolute path (forward slashes) — robust vs Windows shell var expansion.
Verified: hook recalls stored entries, ~1.55s latency (under 3500ms cap).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Hook script that runs ruflo memory search per prompt and injects top
matches as additionalContext. Fail-open (error/timeout -> empty inject,
exit 0, never blocks). Pure-function core unit-tested via node --test.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The H7 fix needs two operations on the global ruflo install: the
getBridge() patch AND disabling the duplicate nested onnxruntime-node
(@xenova/transformers' 1.14.0 vs the hoisted 1.24.3 — DLL name collision
=> ERR_DLOPEN_FAILED). The re-apply script now does both so the whole
fix survives a ruflo update.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Code-review fixes: guard pathToFileURL against undefined argv[1];
reject unrecognised flags with exit 2 before any filesystem access
(prevents a --revert typo from silently applying the patch).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Idempotent script that forces @claude-flow/cli getBridge() to return null
so ruflo memory ops use the persisting raw sql.js path. Pure-function core
unit-tested via node --test.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Design for 3 deliverables (brainstorming output):
- D1: install standalone claude CLI to unblock hive-mind spawn --claude
- D2: fix H7 memory-persistence bug — patch getBridge() so memory ops
use the persisting raw sql.js path instead of the non-flushing
AgentDB-v3 bridge
- D3: UserPromptSubmit advisory hook injecting ruflo memory recall
cspell-words.txt +11 Russian IT-slang inflections used by the spec.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Phase 6 lychee regression выявил 2 broken-link в
docs/superpowers/plans/2026-05-15-ruflo-big-bang-integration.md:680 —
template для CHANGELOG_claude_md.md entry имел relative paths
`(specs/...)` и `(plans/...)` которые резолвились в
docs/superpowers/plans/specs/... и docs/superpowers/plans/plans/...
(double-prefix, файлы не существуют).
Fix: changed к correct relative form:
- specs/... → ../specs/... (parent dir)
- plans/... → 2026-05-15-ruflo-big-bang-integration.md (same dir, bare
filename)
Per Pravila §4.7 п.4 + memory quirk 76: relative paths from plans/specs
require explicit `../<sibling>/` или bare filename для same-dir.
Lychee post-fix: 487 OK / 0 errors (was 485 OK / 2 errors pre-fix).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Code-review fix для commit e0bbf4d (G2 AdminSupplierPricesView errors):
I-2 (load() coverage gap): Добавлен 1 test «load() sets fetchError when
axios.get rejects». Раньше load() error handling (try/catch + fetchError
ref + v-alert warning) реализован но без test coverage. Reviewer flagged
как low-risk gap. Now covered.
Tests 8/8. Регрессий 0.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
axios.patch теперь в try/catch с extractErrorMessage() helper. Per-row
ошибки — reactive errorMessages: Record<number, string> отображаются как
v-icon mdi-alert-circle с v-tooltip рядом с кнопкой «Сохранить».
Success — v-snackbar (3s timeout, color=success, bottom-right) с именем
поставщика.
Retry на той же строке очищает предыдущий error перед новым axios.patch.
load() тоже обёрнут — fetchError ref + v-alert warning сверху таблицы.
+3 Vitest specs (save error / save success / retry clears error).
Регрессий 0.
Closes audit ID G2 from docs/superpowers/specs/2026-05-15-portal-audit-design.md.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Code-review fixes для commit 72a0064 (G1 AdminPricingTiersView errors):
I-1 (mock leak risk): Добавлен afterEach(() => vi.clearAllMocks()) в
новый describe block. Раньше axios.isAxiosError.mockReturnValue(true)
оставался активным после run'а нового describe. Сейчас нет других
тестов после G1 describe в файле — но future-proof против перестановки
test order.
I-2 (coverage gap): Оба success теста (submit + confirmDelete) теперь
assert vm.successToastOpen === true. Раньше тест мог пройти, если
кто-то забыл successToastOpen.value = true в impl — message set, но
snackbar не открыт. Now covered.
Tests 9/9. Регрессий 0.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
axios.post/delete теперь обёрнуты в try/catch с extractErrorMessage()
хелпером из api/client.ts (same pattern as AdminSystemView.vue:32-45).
errorMessage отображается в v-alert (closable, type=error, tonal),
successMessage — в v-snackbar (color=success, 4s timeout).
На failed submit диалог остаётся открытым чтобы пользователь мог
исправить и повторить (UX-pattern). saving=false гарантированно
сбрасывается в finally.
+4 Vitest specs (submit error / submit success / delete error / delete success).
Регрессий 0.
Closes audit ID G1 from docs/superpowers/specs/2026-05-15-portal-audit-design.md.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
window.alert блокирует UI thread, не accessible (a11y), breaks браузерный
automation (Playwright/Selenium). Заменено на v-snackbar (timeout 6s,
color warning, location bottom-right, кнопка «Закрыть»). Текст идентичен:
«Применено: N. Пропущено: M (конфликт с уже доставленными лидами).»
+2 Vitest specs (snackbar opens / snackbar НЕ opens at skipped=0).
window.confirm для pause/resume/archive намеренно оставлен — это
deliberate blocking прерывание для деструктивных операций (UX-pattern).
Closes audit ID C5 from docs/superpowers/specs/2026-05-15-portal-audit-design.md.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Code-review fixes для commit 9068005 (C4 KanbanView DnD persist):
I-2 (test coverage gap): Revert test «onColumnChange reverts...» теперь
seed'ит deal в dealsByStatus['hot'] до вызова onColumnChange (имитируя
vuedraggable mutation pre-event). После failed transition — assert
карточка удалена из hot + восстановлена в new. Раньше array-revert
branch в KanbanView.vue:80-87 (splice + push) имел 0 test coverage —
findIndex возвращал -1, splice silent. Теперь coverage 100%.
I-3 (stale JSDoc): File-header comment в KanbanView.vue lines 7-16
обновлён — описывает actual behavior после Task 2 (optimistic + API call
+ revert). Раньше явно врал «не входит в этот коммит: PATCH /api/deals/
{id}» когда POST /api/deals/transition уже реализован.
Регрессий 0.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Drag-drop между колонками теперь сохраняется в БД через существующий
DealBulkActionController@transition endpoint (single-element массив).
Optimistic UI update (statusSlug меняется сразу) + revert-on-fail с
toast «Не удалось переместить — восстановлен исходный статус».
Без auth.user.tenant_id (dev/demo без login) — local-only mode, API не
зовётся (graceful degradation).
+3 Vitest specs в KanbanView.spec.ts (success / revert / no-auth skip).
Pest covered by existing DealTransitionTest. Регрессий 0.
Closes audit ID C4 from docs/superpowers/specs/2026-05-15-portal-audit-design.md.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Code-review fixes для commit 4e77947 (C2 FilterChip popovers):
I-4 (latent interaction bug): Удалена двойная open-path в FilterChip
activator. v-menu сам управляет projectMenuOpen/managerMenuOpen через
activatorProps. Draft-state копируется при menu open → true через
watch(menuOpen, ...). Раньше:
- Activator click: menuOpen=true
- @click on FilterChip: onRedesignFilterClick → menuOpen=true (duplicate)
- Re-click для close: activator toggles false → onRedesignFilterClick
forces true back → menu не закрывается.
I-2 (inline toggle extract): Multi-line ternary @click заменён на
named methods toggleProjectDraft(proj) / toggleManagerDraft(name).
Консистентно с existing clearProjectDraft / clearManagerDraft. Также
unit-testable независимо от template.
onRedesignFilterClick остаётся для Status chip read-only behavior (P2
backlog Sprint 5). defineExpose обновлён: убран onRedesignFilterClick,
добавлены toggleProjectDraft/toggleManagerDraft/clearProjectDraft/
clearManagerDraft (для будущих spec'ов).
Vitest 3/3 C2-specs обновлены на прямой trigger projectMenuOpen=true
+ $nextTick (watcher seeds draft). Регрессий 0.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- projectsStore: Project.regions?: number[] interface field
- NewProjectDialog: replace interim placeholder с v-autocomplete (89
subjects + federal district subtitle); form drops region_mask/region_mode
(backend dual-writes)
- ProjectDetailsDrawer: replace maskToCodes/encode-watch с direct
form.regions binding; same v-autocomplete component
- Vitest: +2 NewProjectDialog tests (count=89, POST payload includes regions[]);
refactor 3 existing PDD region tests на regions[] model
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
SyncSupplierProjectsJob::adaptProjectsForAllocator no longer converts
8-bit region_mask via bitmaskToList. Instead direct-copies projects.regions[]
(89-code subject array) into supplier_projects.current_regions / DTO.
region_mask still dual-written for PhonePrefixService backward-compat (Plan 6.5
cleanup will switch readers and drop dual-write).
+2 Pest tests verifying direct copy + empty-array semantics.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
89 субъектов РФ по конституционному порядку (ст. 65, ред. 2022).
Adds federalDistrict field for UI group-by + FEDERAL_DISTRICT_NAMES map.
Sentinel code:0 "Вся РФ" сохранён для UI hint; в БД = regions=[].
Plan 6 (см. docs/superpowers/specs/2026-05-14-plan-6-regions-subject-level-design.md).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds INT[] column + GIN index to support 89-code regions (Plan 6).
region_mask/region_mode kept for backward-compat (DEPRECATED, removal in Plan 6.5).
Empty array semantically equivalent to legacy region_mask=255 (all of Russia).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Job dispatch fell с SQLSTATE[42P01] "Undefined table: jobs" when
QUEUE_CONNECTION=database, потому что db/schema.sql не содержит таблиц
jobs/job_batches (CLAUDE.md §6 claim "3 default Laravel-миграции удалены"
не имел эквивалента для jobs в нашей schema; verified via
Schema::hasTable('jobs') = false).
Switch to redis — соответствует prod spec CLAUDE.md §2 "Кэш/очереди = Redis 7"
и существующему Memurai service (Redis 7-compat) per memory quirk #35
(PONG verified Task 4).
Verified end-to-end:
- php artisan config:clear
- config('queue.default') = redis
- Queue::connection('redis') instanceof Illuminate\Queue\RedisQueue
- SyncSupplierProjectsJob::dispatch(1) → Redis::llen('queues:default')
delta=1 (before=0, after=1, cleanup successful)
- Pest --parallel 742/739/3sk/0
- Vitest 758/3sk/0
Local app/.env (gitignored) уже на redis с прошлой сессии; этот commit
синхронизирует normative .env.example для new env setups.
Note: db/schema.sql миграция jobs/job_batches таблиц отложена (redis driver
= no DB queue tables needed).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
In-place port региона multi-select autocomplete в ProjectDetailsDrawer.
Закрывает Out-of-plan «Region multi-select autocomplete» из parent spec
(2026-05-14-project-details-drawer-design.md §7).
Подход A (утверждён 2026-05-14):
- v-autocomplete :items="REGIONS.filter(r => r.code !== 0)" (без sentinel)
- reverse-decompose existing region_mask в codes[] при reseedFromProject
- watch selectedRegions → encode mask + mode (include когда пусто, exclude иначе)
- 3 новых vitest case: render chips / select-encodes / clear-resets
Backend без изменений (region_mask + region_mode payload уже в Task 5 onSave).
Backport reverse-decompose в NewProjectDialog (TODO line 172) — out of scope.
cspell-words.txt +1 (иммутабельны).
.conflict-item теперь использует динамический bg из CONFLICT_TYPES[type].bg, эмодзи-префикс + цветной name из CONFLICT_TYPES[type].color. Сортировка через CONFLICT_TYPES[type].rank (RED=1, BLACK=2, GREEN=3) — 🔴 не закрыт правилом → ⚫ возник на практике → 🟢 закрыт правилом. Footer cat-legend заменил 1 «— конфликт» бэйдж на 3 цветных. Iter2 spec §4.3 — last code task.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
#legend-panel разделён на 2 containers: #legend-node-content (existing) + #legend-edge-content (new, hidden default). На click по ребру открывается edge layout с 7 полями (источник/получатель/тип связи/когда/что передаёт/обязательность/регламент). showLegend переименована в showNodeLegend; новая showEdgeLegend. Click handler dispatches node vs edge. Iter2 spec §5.4, §5.5.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Новый объект EDGE_DETAILS — для каждого ребра 5 полей (type/when/transfers/mandatory/rule). Источник и получатель derived from from/to при рендере в T8. Покрытие 100% — все рёбра имеют запись. Тип связи: enum из 9 (содержит/подчиняет/координирует/читает/запускает/документирует/триггерит/альтернатива/конфликт). Iter2 spec §5.1, §5.2, §5.3.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
T6 spec review нашёл orphan item: hookify_plugin conflicts array имел 2 items (PreToolUse:CLAUDE.md-warn + economy-mode хук), но в spec §4.2 классифицирован только первый (8 рёбер, hookify↔hk_economy не среди них). Item 2 без canvas edge counterpart. Remove restores invariant: 16 NODE_DETAILS conflicts items = 8 edges × 2 sides.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Переписаны nd() блоки для 10 lefthook jobs (lh_gitleaks/lh_mdlint/lh_cspell/lh_stylelint/lh_pint/lh_larastan/lh_squawk/lh_eslint/lh_gitleaks2/lh_lychee) и 15 memory-файлов. Уточнено что «pre-commit stage» = «перед каждым коммитом», «stage_fixed:true» = «авто-сохранить исправленное». Iter2 spec §3 group D. Last text-rewrite task.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Переписаны nd() блоки для 11 агентов (ag_pest/ag_rls/ag_explore/ag_general/ag_plan/ag_guide/ag_statusline/ag_hookify/ag_pcreator/ag_pvalid/ag_skreview) и 7 MCP (mcp_pw/mcp_gh/mcp_boost/mcp_semgrep/mcp_sentry/mcp_redis/mcp_21st). Иностранные аббревиатуры расшифрованы (SAST/CVE/SQLi/XSS/ПДн). Iter2 spec §3 group C.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Переписаны nd() блоки для pravila/claude_md/psr_v1/tooling/superpowers/fd_plugin/upm/claude_md_mgmt/hookify_plugin. Жаргон-блэклист (hard rule, matcher, pipeline, override, peerDep и др. — 11 терминов) убран; параграф-ссылки сохранены как примечания в скобках. Iter2 spec §3 (Style Guide + group A).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
После T1 code-quality review: 2 Important issues из spec §9 mitigation list. (1) try/catch обернул read/write localStorage — в Edge InPrivate / quota-exceeded не падает, fallback на default 300. (2) network.redraw() rAF-throttled через redrawScheduled flag — устраняет potential jank при fast drag на медленном hardware (mousemove может fire'ить >60Hz).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Drag-handle 6px на левой границе #legend-panel (cursor:col-resize, hover-bg #0d4a5a), JS-обработчики mousedown/mousemove/mouseup, clamp [300, 900]px, сохранение ширины в localStorage ключ liderra-map-legend-width, restoration on DOMContentLoaded. После каждого resize вызывается network.redraw() для пересчёта vis.js canvas. Iter2 spec §2.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
qitem + skreview — фрагменты идентификаторов узлов карты (sk_qitem, ag_skreview); cspell токенизирует по `_` и видит их как unknown words. Упомянуты в plan-файле как ссылки на task'и/инструменты. Iter2 plan reference.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
зарелизен + отрефакторен (русифицированные tech-термины «released» / «refactored»; используются в iter2 spec §0 Context); cdesc (CSS class из docs/automation-graph.html .conflict-item .cdesc, ссылка в iter2 spec §4.3 renderer changes).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
A11y rescan Pattern H — Vuetify <v-text-field> без `label` prop рендерит
empty `<label id="input-v-NN-label">` (referenced via aria-labelledby).
Pa11y/axe видит unlabelled input на /admin/billing (search «Поиск по
названию или ИНН») и /admin/system (search «Поиск по ключу или описанию»).
Initial naive fix добавил `aria-label="..."` — но ARIA priority говорит
aria-labelledby overrides aria-label, поэтому осталось violation.
Final fix: add `label="Поиск"` prop on VTextField. Vuetify рендерит
floating label с правильным accessible text → axe-core resolves через
aria-labelledby chain successfully. Placeholder сохранён (split: «Поиск»
теперь в label, «по названию или ИНН» / «по ключу или описанию» —
placeholder).
Files:
- AdminBillingView.vue:209-217
- AdminSystemView.vue:130-138
Closes Pa11y «label» violations на 2 admin URLs.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
A11y rescan Pattern A — Vuetify <v-app-bar-nav-icon class="d-md-none">
без accessible name. Pa11y/axe видит button в DOM даже на desktop где
он hidden via CSS — флагает «button-name» violation на 9 AppLayout views
(/dashboard, /deals, /kanban, /projects, /billing, /settings, /reports,
/reminders, /admin/tenants).
Fix: AppTopbar.vue:90-94 — `aria-label="Открыть меню навигации"`.
Closes 9 of 14 authenticated routes' a11y violations (down 14→5 affected
URLs after this commit).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
11-task plan для повторного a11y-аудита: extend Pa11y от 7 guest URLs к 21
URLs (включая 14 authenticated через per-URL actions login flow), + axe-core
cross-validation via Playwright MCP, + inline fixes для real prod findings.
Closes Audit #3 Phase 7 «authenticated pages out of scope» clause per
explicit user request «Pa11y был настроен на старые HTML-эскизы, проведи
повторно аудит в этой части, чтобы он проверил реальный портал».
Plan: docs/superpowers/plans/2026-05-14-a11y-rescan-live-portal.md
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Final audit rollup: 0 P0 / 1 P1 / 11 P2 / 14 P3 (26 total).
Pa11y P1 decision: FIX-DEFER with concrete migration plan
(6 acceptance criteria + 60-120 min estimate). Decision driven by
3-hypothesis analysis: (1) config-only swap surfaces new live-app
violations (color-contrast on DevIndexBadge, region landmarks),
(2) additive both-kept keeps handoff failures blocking CI,
(3) deferred migration with proper sprint task is cleanest path.
Both decision-matrix triggers from brief apply: risk of new
failures without follow-up plan + new CI infra requirement
(live dev server lifecycle).
Carryforward audit: 9 items still open from Audit #2 (all
P2/P3, no regressions). 11 Audit #2 items verified closed in
this audit (bf84568 aria fix, CTO-19 Lucide, Q.DEFER.001-004,
quirks #62/#72/#80, cron, RUNBOOK.md).
FIX-NOW this session: 0 commits (Pa11y deferred per matrix).
FIX-NOW earlier in audit: 1 commit (823da29 cspell inline).
FIX-DEFER documented: 25.
BLOCKED: 0.
Verdict: GREEN — 0 P0, sole P1 is methodology audit-fidelity gap
(Pa11y declared but not exercised against live code); axe-core
via Playwright in Phase 7 provides actual a11y coverage with 0
real prod issues against DevIndexBadge temp feature.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
CsvReconcileJobTest used Bus::fake() (all jobs), silencing dispatch_sync of
RefreshSupplierSessionJob when a parallel afterEach wiped supplier:session.
Now: Bus::fake([RouteSupplierLeadJob::class]) + anonymous mock that re-puts
the session in handle(), making race-window recovery deterministic.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
DatabaseTransactions did not prevent cross-session data accumulation in
liderra_testing; count assertions drifted (1465 managers, 519 projects).
RefreshDatabase runs migrate:fresh once per session (RefreshDatabaseState::migrated)
so stale data is wiped at start of each composer test run.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Single-file HTML visualization of Лидерра CRM automation system.
vis.js 9.1.9 force-directed graph: 9 color groups (rules/plugins/skills/hooks/
agents/MCP/lefthook/memory), 6 red dashed conflict edges, click-to-legend panel
with 5 sections (что делает / кому подчиняется / кто / одновременно / конфликты),
search + freeze/unfreeze/reset/clear toolbar. Solarized dark theme.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sprint plan B.1/B.2/B.3/A.1/A.2/A.3. Fixes: broken ../../../memory/
link → plain text; cspell-words.txt +аутит (Russian IT verb).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Audit #2 Phase 10.2 P2: axe-core 4.10 reported aria-tooltip-name
violation — <div role="tooltip"> had no accessible name. Adding
aria-label to <v-tooltip> passes it through to the rendered overlay.
Verified: axe-core on /admin/tenants — 0 tooltip violations post-fix.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Audit #2 Phase 14 P2: partition tables were not auto-created.
Without this entry the scheduler never called partitions:create-months,
causing partition exhaustion on the first day of each new month.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
fake()->unique()->words(3,true) fixes quirk #77 deterministic collision
on projects(tenant_id,name) UNIQUE in --parallel runs.
test:parallel alias = pest --parallel --recreate-databases (quirk #62/#73).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Поддержка для CLAUDE.md v1.92 шапка. «нормативки» (genitive) уже в словаре —
inflection-blind cspell не распознаёт «нормативку» автоматически.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Применены 3 edits per Task 9 drafts (commit 00eb8ad):
- Шапка: v2.0 → v2.1 от 13.05.2026 day +1; L4 narrative +упоминание debug-runtime MCP
- R10.1 Блок 3 (MCP-серверы): +2 строки sentry + redis с категорией debug-runtime
- История версий: +v2.1 entry перед v2.0
NB по drafts correction: drafts указывали "Блок 1" — actual right block для MCP serverов = Блок 3 (MCP-серверы по `~/.claude.json` / `.mcp.json`).
Категория debug-runtime introduced — отдельная от UI-пула (Pravila §13) и infrastructure
(claude-md-management). READ-ONLY usage, не trigger'ит R6.0/R6.1 фильтры, не входит в R14 pipeline.
Связано: Tooling v1.16 → v1.17 (763aeae), CLAUDE.md v1.91 → v1.92, Pravila v1.12 → v1.13.
PR #3 (cc5f63b) merge precedent.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Поддержка для Tooling v1.17 §4.9 Redis MCP entry:
- wenit — npm пакет автор (@wenit/redis-mcp-server, post-MVP migration candidate)
- FLUSHDB, LPUSH — Redis команды (forbidden в READ-ONLY usage)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Markdownlint MD033 (no-inline-html) caught <cmd> and <output> placeholders
on line 63 of constraints section as HTML elements. Wrapped в inline-code
backticks.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Project-local subagent в .claude/agents/pest-parallel-debugger.md.
Specialized для верифицированных Pest --parallel квирков 72 + 73
в проекте Лидерра (memory feedback_environment.md lines 385, 389):
- quirk 72 — Redis supplier:session race в subdir-only run
- quirk 73 — cumulative state на long sessions
4-hypothesis diagnostic pipeline (real / quirk 72 / quirk 73 / other).
READ-ONLY (tools: Read, Grep, Bash).
NB: quirks 70-71 в memory — про a11y/Vuetify, не Pest — не входят в agent's scope.
Quirks 74-76 — про npm/Lucide/plans paths, тоже не Pest.
Замена generic systematic-debugging для повторяющихся flake патернов.
NB: project-local subagent auto-discovery может требовать session restart.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
PostToolUse hook на Edit|Write matcher — emits stdout reminder если file path
matches regex `(^|/)db/schema\.sql$` (Windows backslashes normalized к `/`).
Runtime enforcement существующего правила CLAUDE.md §5 п.8:
"Не править db/schema.sql без записи в db/CHANGELOG_schema.md."
Self-review (§8) ловит это поздно (после ≥3 групп правок); hook — сразу,
в transcript stdout vs stderr (visible alongside markdownlint output).
Параллельный entry в hooks.PostToolUse array — Claude Code processes oба
markdownlint (для .md без CLAUDE.md) + schema reminder (для db/schema.sql)
независимо на каждом Edit|Write.
Edge case: Bash-обход (echo ... >> db/schema.sql) не покрывается —
known limitation, документировано в spec §4.6.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
PreToolUse hook на Edit|Write matcher — emits stderr warning если file path
exactly === <project>/CLAUDE.md (path.resolve compare, AND CLAUDE_FILE_PATH +
CLAUDE_PROJECT_DIR both injected by Claude Code at hook firing).
Runtime enforcement существующего правила CLAUDE.md §5 п.10:
"Не править этот CLAUDE.md напрямую — только через плагин claude-md-management."
Option A (warning-only) chosen per Task 1 pre-flight Q5: skill-marker detection
ненадёжно в текущей Claude Code (CLAUDE_SKILL_ACTIVE env var inconclusive в Bash
session — injection-only при hook firing, не verifiable без live test). Warning
visible в transcript stderr; если invoked via /claude-md-management:*, warning
информационный, не блокирует.
Не trigger'ит для:
- app/CLAUDE.md (Boost-managed, не существует на момент implementation)
- node_modules/*/CLAUDE.md (если есть — не root project)
Edge case: Bash-обход (sed -i CLAUDE.md или > CLAUDE.md) не покрывается —
known limitation, документировано в spec §4.5.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Memurai (Redis 7-совместимый Windows service, localhost:6379).
Pending формализация в Tooling §3.3 #35 — sync нормативки отдельным планом.
Package: @modelcontextprotocol/server-redis@2025.4.25 — DEPRECATED
по npm статусу («Package no longer supported»), но Anthropic source,
простой протокол, рабочий. Post-MVP migration на community alternative
(e.g., @easy-mcps/redis-mcp-server@1.0.8 или @wenit/redis-mcp-server@1.0.3)
когда подтвердим trust.
READ-ONLY use — отладка очередей, кэша, Pest --parallel quirk 72.
Gitleaks scan (manual via absolute path): no leaks found.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Skeleton files findings/blocked/report для portal full audit #2 (2026-05-13).
Phase 0 finding P3: обнаружена параллельная сессия на feat/claude-automation
branch (claude-automation-recommender skill активна параллельно с этим audit'ом
на main). Main verified clean, git checkout main вернул state. CWD persistence
quirk зафиксирован для memory (двойной cd app && ... загнал в app/app/).
cspell-words.txt: +«инвалидирует» (валидное слово для Phase 0 finding prose).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Design для нового 14-phase audit pass на main 21262ef post-merge plan5→main.
Scope: full 13-phase audit (replica 12.05 структуры — pre-flight, static analysis ×4 subagents, test suites, schema integrity, security, UI smoke 24 views, cross-doc, categorize, fix loop, regression verify, Pa11y live + axe-core, TODO sweep, bundle analyzer, Vitest coverage) + новая Phase 14 pre-production readiness (Sentry, DB roles, mock-data prod-gate revisit, CI workflows audit, env validation, queue/cron, backup/log rotation, deployment runbook).
Fix-strategy: hybrid — P0+P1 → atomic commits на main по ходу; P2/P3 → только запись в findings.md (без commits).
Guardrails applied (lessons из 12.05 audit + Pravila v1.12):
- Phase 4 SAST: ls .github/workflows/ FIRST (audit methodology gap closure)
- Phase 5/10 UI-refactor visual smoke + axe-core с setTimeout 500ms + hard reload (Q.DEFER.004 lesson)
- Pest --parallel --recreate-databases для long sessions (квирки 62/73)
- Plans/specs relative paths ../../../ для app/ refs (Pravila v1.12 §4.7 п.4)
- npm install с --legacy-peer-deps (квирк 74)
Baseline для regression gate Phase 9: Pest 742/739/0/3, Vitest 88f/683/3sk, Vite ~3.5s/0err, Histoire 35/63.
Next step: invoke superpowers:writing-plans для implementation plan в docs/superpowers/plans/2026-05-13-portal-full-audit-2.md.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Слова требуются для unblock pre-commit lefthook на untracked .md в working tree:
- `доразбор` — валидная русская приставочная форма (audit spec scope-decisions).
- `нормативки` — генитив-форма от «нормативка», стандартный проектный термин.
- `нерегрессии` — отрицательная форма от «регрессия» (audit verdict).
- `ver` — стандартная аббревиатура version/release context.
- `hookify` — название плагина из тулчейна (упоминается в memory + skill list).
- `pункт` — mixed-script typo (Latin `p` + Cyrillic ункт) добавлен в audit-cited
artefacts секцию рядом с импersonator/proverено/моменти. Owner оригинального
файла видит typo сам — словарь только разблокирует cspell на untracked work-in-progress.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Prepares dictionary для предстоящего audit spec/plan/findings/blocked/report
артефактов в этой и следующих сессиях.
- закоммиченных — валидная форма уже существующего `закоммичены`, нужна для
описаний git-state в audit-докуменах.
- AKIA — AWS access key prefix, упоминается в production secrets scan
(Phase 4 audit) как regex anchor.
- gpg — стандартное security-обозначение (GnuPG), используется в decision-tree
hard-stops («никаких --no-gpg-sign»).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Lychee pre-push hook нашёл broken link: `[app/resources/js/plugins/vuetify.ts](app/resources/js/plugins/vuetify.ts)` resolves к `docs/superpowers/plans/app/...` (несуществующий путь). Fix: `../../../app/resources/js/plugins/vuetify.ts` (3 levels up from plan-file location).
Pravila: prefer new commit over --amend; lychee block requires fix перед push.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Auto-generated by vite watcher during a11y-fix session 12.05.2026 evening:
— 1616: DashboardBalance.vue:32 div role=img (.runway-bar aria-prohibited-attr fix)
— 1617: KanbanView.vue:164 div role=region (scrollable-region-focusable fix)
— 1618: AdminLayout.vue:88 v-list role=navigation (aria-required-children fix)
Quirk 64 caveat: dev-indices обычно идёт в logical commit с UI-change.
Здесь catch-up от ранее закоммиченных fix'ов (Q.DEFER.002 sub-B batch),
отдельным atomic — приемлемо как cleanup audit-хвоста.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
HTML visual reference for Direction A Quiet Luxury portal redesign
(12.05.2026 sessions). Companion to spec/plan markdown files уже в репо
(docs/superpowers/specs/2026-05-12-portal-redesign-*.md и
docs/superpowers/plans/2026-05-12-portal-redesign-*.md).
Memory ref: project_portal_redesign.md (20 commits на plan5-frontend-projects)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Planning artefacts from 10.05.2026 brain-extraction work (tag brain-v1.0
at 52584df in claude-brain repo at c:/моя/проекты/claude-brain/).
GitHub push 8.2 remains BLOCKED — artefacts captured for traceability.
Memory ref: project_claude_brain.md
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
— Worktree artefacts from Superpowers using-git-worktrees skill
(Pravila §11.3 — может быть нестабилен на Windows + кириллица,
но директория появляется при попытках)
— Vitest --coverage output (app/coverage/), не должен попадать в commits
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
В рамках post-audit continuation session 12.05.2026 ночь обнаружен factual
error в v1.88: коммит 615db99 в двух местах представлен как Plan 4 merge,
коммит f4ec5dc как PSR_v1 R15 removal. Оба идентификации неверны.
Verified через git log origin/main + git show <commit>:
- 615db99 = «chore(rules): remove R15 motion-runtime restrictions (PSR_v1 v2.0)» (12.05.2026 07:30) — R15 removal, НЕ Plan 4 merge
- 8681040 = «docs: Plan 4 closure — CLAUDE.md v1.87 + Открытые_вопросы v1.78» — правильный Plan 4 closure marker на origin/main
- a907fea..174dbae = backend Plan 4 task-коммиты (Tasks 9-11), merged ранее
- f4ec5dc = «fix(redesign): sidebar position:fixed + main padding-left» — Quiet Luxury sidebar hotfix на ветке plan5-frontend-projects, НЕ на origin/main, НЕ R15 removal
Правки v1.89:
1. §6 строка обновлена с правильными коммитами + явное разделение «Plan 4 closure 8681040» и «R15 removal 0fd93fd + 615db99» как разные истории
2. Шапка v1.88 changelog inline: 615db99 → 8681040 + NB-маркер про factual error
3. §9 v1.88 entry inline: то же исправление + NB
4. Bump CLAUDE.md v1.88 → v1.89 (новая шапка)
5. Новая v1.89 entry в §9 CLAUDE.md + параллельная запись в CHANGELOG
6. CHANGELOG intro обновлён: документировано что v1.84..v1.88 живут inline в §9 (CHANGELOG-обслуживание не велось 10.05.2026–12.05.2026)
Связанные документы (Pravila v1.10 / PSR_v1 v1.7 / Tooling v1.15 / реестр
v1.77 на ветке plan5-frontend-projects) НЕ требуют изменений — фикс
локален в CLAUDE.md.
Источник: post-audit continuation session, bonus-finding во время Q.DEFER.001
(memory description downgrade). Заказчик: «доделывать аудит, поправить
ошибку в CLAUDE.md». Через /claude-md-management:claude-md-improver per
CLAUDE.md §5 п.10.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
User chose variant (B) Semgrep в CI for Q.INFO.001. Investigation shows
.github/workflows/sast.yml already exists from PR #25 commit 53fb1ec
(10.05.2026, 2 days before audit) with better-than-minimal config:
- semgrep/semgrep-action@v1
- configs p/php + p/javascript + p/typescript + p/secrets
- triggers push/PR на main with path-filters app/app, app/resources/js, app/database/migrations
- SARIF upload to GitHub Security tab via github/codeql-action/upload-sarif@v3
Audit Phase 4 Subagent G missed this — searched only for local `npx semgrep`
CLI without checking existing CI workflows. Tagged as audit-gap finding for
future Phase 4 improvement (check `.github/workflows/` first).
No new code required. +SARIF added to cspell-words.txt.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
После Phase 12 P3 finding R4-R5 (vendor chunk renaming) — попытался применить
`build.rollupOptions.output.manualChunks` в vite.config.js. Vite 8 использует
Rolldown который требует function-form (object-form ломает с
"manualChunks is not a function"). Под function-form Rolldown засосал
все consumers stores в pinia chunk через transitively-import резолюцию:
- Pinia chunk implicit ~5kB → explicit 127kB raw / 50kB gzip
- Total critical-path payload +50 kB gzip vs baseline (net negative)
- Vite auto-split работает better для этого app shape
Reverted to baseline. "VBtn 184 kB" — naming artefact (auto-named первый
Vuetify consumer'ом), не actual perf-issue. R4-R5 closed без code fix —
informational only.
3 гипотезы про cause Pinia blow-up:
- H1 stores transitively-pulled через pinia API import
- H2 cycles vue-core↔pinia в Rolldown greedy chunking
- H3 return null в function manualChunks ломает auto-split fallback
Detailed reverification recommended next session если решим повторить
с `output.preserveModules` или per-store individual manualChunks rules.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
После follow-up прохода — обе a11y contrast violations исправлены:
- ErrorView support-link (fff2dff) — 2.77 → ~12:1
- ForgotPasswordView info-alert (5cebe24) — 4.18 → ~7.5:1
Final Pa11y baseline на guest URLs: 4/4 No issues found.
Остаётся auth-views coverage (16 views) — требует session cookie
в Pa11y, defer next session.
+неверифицированы в cspell-words.txt.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Phase 6 audit found inconsistency in routes/web.php SPA-shell list.
Comment (line 188-190) declares «Регистрируем явно, а не catch-all»
for test isolation, but the explicit list missed:
- /reminders, /projects (main views from Plan 5)
- /admin and 7× /admin/* (added in Plans 4 + 5)
These paths worked via Route::fallback (line 211), but that risks
runtime-routes from Pest beforeEach('_test/*') being shadowed by
fallback BEFORE catch-all. Align explicit list with router/index.ts
to honor the documented rationale.
No behavioral change for production (same welcome view returned);
test-suite isolation contract restored.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
vue-tsc was emitting 9 errors from two issues:
1. ProjectCard.vue had a local `interface Project` missing region_mask /
region_mode / delivery_days_mask, while stores/projectsStore.ts
exported the canonical one with those fields. ProjectsView.vue passed
the canonical Project to ProjectCard handler signatures which expected
the local incomplete one → 5× TS2322.
2. EditProjectDialog passed `project: Project | Record<string, unknown>`
to NewProjectDialog which expected `Record<string, unknown> | null`.
Project lacks an index signature → TS2322.
3. AppSidebar.vue template referenced `item.countKey` not declared in
NavItem interface → 2× TS2339.
Changes:
- ProjectCard.vue: drop local Project, import from projectsStore.
- NewProjectDialog.vue: project prop type → Project | null (was Record).
Drop `as { id: number }` cast on PATCH URL.
- EditProjectDialog.vue: project prop type → Project | null.
- AppSidebar.vue: add `countKey?: string` to NavItem.
- projectsStore.ts: make region_mask/region_mode/delivery_days_mask
optional (backward-compat for mock fixtures; production rows always
populate them by schema).
- Test/story fixtures expanded with delivered_today/is_active/archived_at/
sync_status to match strict Project shape.
Verification:
- npx vue-tsc --noEmit → 0 errors (was 9).
- npx vitest run on 5 affected specs → 16/16 passed + 2 skipped.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
BulkActionsBar.story.vue calls useProjectsStore() in top-level setup,
which executes before story collection. Without Pinia plugin, Histoire
build aborts with `getActivePinia() was called but there was no active
Pinia` — uncaught exception kills the whole build (24 → 0 stories).
Add createPinia() to histoire.setup.ts alongside Vuetify + vue-router.
Also add `/recovery-use` and `/projects` routes to the stub router
(parity with router/index.ts after Plan 5 frontend), so future story
files needing those paths don't emit Vue Router warns.
Histoire build now: exit 0, 35 stories / 63 variants in 80.6s.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Корень: dev-БД `liderra` создавалась с LC_CTYPE=C — lower()/upper() не
делает case-folding для кириллицы, `ILIKE '%сп%'` на «Окна СПб» = 0 строк.
Test-БД с Russian_Russia.1251 маскировала проблему.
Системный fix: dev-БД пересоздана через `LOCALE_PROVIDER icu ICU_LOCALE 'und'`
(PG 16+ ICU collation, кросс-платформенно). Точечный COLLATE-workaround не
понадобился — все 5 ILIKE-endpoint'ов теперь работают с кириллицей без
правки кода. CTO-20 закрыт в реестре v1.81; команда CREATE DATABASE с ICU
зафиксирована для prod-deploy.
Сопутствующее:
- ProjectsView clearable: workaround `::after content '✕'` + видимость
через `.v-field--dirty` (mdi-* font не подключён в проекте — CTO-19
заведён в реестре).
- LookupsTest: удалён stale case `GET /api/projects?tenant_id=N`,
заменённый auth:sanctum-роутом в Plan 5.
- Pest +1 регрессионный тест (`search is case-insensitive for Cyrillic`)
в ProjectsListShowTest, 10/10 / 37 assertions.
- phpstan-baseline регенерирован (3 actingAs + удалённый case).
- cspell-words: +Регистронезависимый, +und.
- app/.backups/ в gitignore.
Verify:
- Pest --parallel: 742 passed / 1 flaky error (CsvReconcileJobTest cache
race, в изоляции 2/2 PASS) / 3 skipped.
- Browser: «сп» и «окн» возвращают «Окна СПб».
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Final code reviewer correctly identified that impl-commit 3fc90f1 included
not only the CSS work but also a template change <v-checkbox> →
<label><input><span> on ProjectCard.vue.
Root cause (Task 0 forensics): session-start git status showed
`M app/resources/js/components/projects/ProjectCard.vue` — pre-existing
uncommitted modifications from prior session/work. When the session Read
the file at start, it saw the working-dir version (already with native
<label><input>), not the branch-HEAD 88a13e2 version (with <v-checkbox>).
Stage+commit in 3fc90f1 thus bundled both changes.
The template change is architecturally required for the new CSS to work —
<v-checkbox> renders Vuetify-internal <input> without a sibling <span>,
which is what the scoped :checked + .card-check__box::after selector
needs. The baseline-fix commit 84530d5 was also prepared for the native
input selector, consistent with this template structure.
Updating spec §2 architecture to reflect this honestly rather than leave
a stale «Template / script нетронуты» statement that conflicts with the
diff in main.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ProjectCard.vue: replace 2px noir solid border on .card-check__box with
1px var(--liderra-line) idle / var(--liderra-line-strong) hover / var(--liderra-teal)
checked. Checked state uses tonal 10% teal bg instead of full fill. Size 20→16px.
Added :focus-visible outline for keyboard nav.
NewProjectDialog.vue: add a local .ld-input-quiet class to all 5 v-text-field
in the dialog (domain / phone / sms keyword / name / daily limit). The class
overrides v-field outline border-color through :deep() to use the tokens.css
1px line / line-strong / teal palette, and sets border-radius to var(--radius-8).
All variant/density/color values come from Vuetify global defaults in
plugins/vuetify.ts:50-54. Includes opacity:1 on every override to neutralize
Vuetify's --v-field-border-opacity 0.38 cascade, plus an explicit error-state
rule with border-color:currentColor to preserve Vuetify's red error border.
Twin elements left out of scope: .toolbar-check__box in ProjectsView.vue,
v-combobox/v-autocomplete/v-btn-toggle inside the same dialog, and the
filter-bar v-select inputs.
Spec: docs/superpowers/specs/2026-05-12-quiet-luxury-elements-1440-896-design.md
Plan: docs/superpowers/plans/2026-05-12-quiet-luxury-elements-1440-896.md
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Task 2 code-quality review (subagent verdict: Ready to merge? No) found
two critical correctness bugs in the original CSS template from spec §3.2:
1. Vuetify's outlined variant collapses sub-element opacity through
--v-field-border-opacity (= 0.38 at idle). Without explicit opacity:1
on each override block, --liderra-line (alpha 0.08) effective alpha
becomes 0.03 → border essentially invisible on ivory backgrounds.
2. Overriding border-color with an explicit value breaks the
currentColor inheritance Vuetify uses for the error state
(color: rgb(var(--v-theme-error)) on .v-field--error.v-field__outline).
Without an explicit error rule that restores currentColor, the red
error border never appears on any of the 5 validated fields.
Also tightened hover from .ld-input-quiet:hover (which is on the .v-input
root, including hint/error message area) to .v-field:hover inside
:deep() — matches Vuetify's own hover scope and avoids triggering on
helper text hover.
Spec §3.2 and plan Task 2.2 updated to the corrected CSS block with
explicit «almost-trap-avoidance» notes documenting why each adjustment
is needed.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Pre-existing failing test from commit c9ee8d8 — data-testid lives on
<label>, but @change handler sits on <input> inside it. jsdom does not
bubble change-event from label to input via @vue/test-utils trigger.
Use child-input selector to fire the event on the right node.
Baseline после fix: 614 passed / 3 skipped / 0 failed (vs 613 / 3 / 1).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Task 0 (pre-flight) обнаружил global Vuetify default в plugins/vuetify.ts:50-54
который уже устанавливает variant=outlined density=comfortable color=primary
для всех VTextField. Изначальная гипотеза spec §1.2 «variant=filled по
умолчанию» была неверна — все 5 v-text-field в NewProjectDialog.vue выглядят
одинаково тёмными (Vuetify default border ≈ 60% on-surface), а не «один
filled среди других».
Заказчик принял расширение области: применить .ld-input-quiet ко всем 5
v-text-field (lines 21, 30, 48, 59, 61), убрать неработоспособные явные
props (variant/density/color/rounded — они уже из global default), и
вынести border-radius в :deep(.v-field) override через --radius-8.
Также Task 0 нашёл pre-existing failing test в ProjectCard.spec.ts:43
(change-trigger на <label> вместо <input> внутри); это будет починено
отдельным atomic-коммитом перед Task 1.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Spec по узкому Quiet Luxury редизайну двух конкретных элементов из
Dev Element Indices: card-check__box в ProjectCard и v-text-field
«Название проекта» в NewProjectDialog. Подход — CSS / prop правки
под существующие tokens.css, без новых primitives.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Delta mode combines Add/Remove numeric inputs into a single signed delta;
Replace mode switches to an absolute value input via v-checkbox toggle.
5/5 Vitest pass; full suite 611 passed + 3 skipped.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Refactor ProjectService::bulkAction to accept full payload array and
return structured {updated, skipped, warnings}. Add bulkUpdateRegions
using PG raw bitmask expr (region_mask | add) & ~remove & 255.
Add stubs for bulkUpdateDays/bulkUpdateLimit (Tasks 3-4). Update
controller to pass merged payload and return service result directly.
Un-todo Task-1 region validation test; add regions bitmask test (18/20).
Update phpstan-baseline: actingAs count 5->6, restore match.unhandled.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace !empty() check with has()+is_array() so scope:{filter:{}} is
accepted as "all projects" rather than rejected as missing selection.
Expand scope.filter to IDs in the controller (500-row limit guard) so
the service receives a typed array[]; add Pest coverage for this case.
Update phpstan baseline count for new actingAs() call.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- BulkProjectActionRequest: add update_regions/update_days/update_limit actions, scope.filter, withValidator for ids-or-scope + delta/replace mutual exclusion
- ProjectBulkActionsTest: 4 new tests (3 pass, 1 todo pending Task 2 service handler)
- ProjectsActionsTest: update > 100 ids limit test to match new max:500
- phpstan-baseline: add 4 actingAs false-positive entries for new test file
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sidebar: убраны Менеджеры/Напоминания; Работа в порядке
Проекты/Сделки/Канбан/Дашборд; Команда — только Настройки;
снят useRemindersStore (был только под reminders badge).
Topbar: тёмный фон linear-gradient(noir → #04261E) совпадающий
с sidebar #1271; убран breadcrumb «Рабочая область»;
v-toolbar__content padding-left:240 (не уходит под sidebar).
DevIndexBadge: top:64 (ниже топбара, не перекрывает user-chip).
Vitest AppLayout 15/15 PASS.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
#1 (review-Important) — Esc now also calls pauseHover(2000) so the next
mousemove doesn't re-target the cursor element within 16ms. User gets
2 seconds to move off before hover re-engages.
#4 (review-Important) — Plugin walker now skips data-dx injection for
inert Vue compiler tags (template / slot / component / Transition /
TransitionGroup / Suspense / KeepAlive) but still recurses into their
children with the tag preserved in ancestor chain (keeps descendant
signatures stable). Manifest regenerated — no more phantom IDs that
reference no-DOM-element nodes.
Other review findings (CI integration, save-amplification, code-style
polish) skipped: this feature is temporary, will be removed at final
release.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Prints file:line/tag/text/parent-chain/signature/created for any manifest
entry. Handles deleted IDs (tombstones) with separate message format.
Exit codes: 0=found, 1=not-found-or-no-manifest, 2=usage-error.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
IDE auto-completion/validation for app/dev-indices.json via the $schema
reference in the manifest header.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Утверждённый дизайн: Vite plugin инжектирует data-dx на каждый element
+ persistent dev-indices.json (commit'ится) + DevIndexOverlay
(hover/Alt-keys/Alt+Shift+I toggle/click-to-copy).
Cтабильность через structural signature (file + ancestor chain + tag +
static attrs + text snippet), tombstones для удалённых ID, escape-hatch
через data-dev-name на важных местах. Production: tree-shake'ится через
import.meta.env.DEV.
+3 слова в cspell-words.txt (реордере/реорден/hmr).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Hotfix: после Task 12 замены v-navigation-drawer на plain <aside> sidebar остался position:static и толкал v-main в flow ниже (y=901), весь контент уезжал за viewport. Добавлен .ld-sidebar position:fixed top:0 left:0 height:100vh z-index:1006 + .app-main padding-left:232px. Verified via Playwright snapshot — Dashboard KPI/charts отрисованы корректно.
Brainstormed via superpowers:brainstorming. User decision 12.05.2026:
remove R15 PSR_v1 section entirely (variant B). Conscious rollback of
audited construction from v1.83 (10.05.2026).
Spec: docs/superpowers/specs/2026-05-12-remove-r15-motion-restrictions-design.md
Plan: docs/superpowers/plans/2026-05-12-remove-r15-motion-restrictions.md
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Schema CHECK constraint on projects.region_mode accepts только 'include'/'exclude'.
Spec/plan изначально использовали 'all'/'whitelist'/'blacklist' (semantic naming),
что не соответствует БД-схеме. При имплементации Task 3 implementer выбрал
'include'/'exclude' (match schema = source of truth). Propagate-fix:
- plan (2 PHP Rule::in + ~10 payload mentions + 4 TS form defaults)
- spec (§4.2 описание, 3 JSON API examples, §6.4 текст, §7.1 StoreProjectRequest)
Чтобы Task 5+ (UpdateProjectRequest, frontend tasks 7-11) не повторили
плановую ошибку.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
I-1/M-1: introduce resolvedSupplierProjects() private helper on Project
model; rewrite aggregateSyncStatus(), aggregateLastSyncedAt(),
getSupplierLinks() to read from eager-loaded supplierB1/B2/B3 relations
instead of SupplierProject::find() — eliminates up to 120 SELECTs/page.
I-2: aggregateLastSyncedAt() now uses sortBy(timestamp) instead of
Collection::min() on Carbon objects (string-comparison was unreliable).
M-2: add explanatory comment on intval+array_filter silent-drop behaviour
in the ?ids batch-fetch path.
M-3: new test — ?ids batch silently excludes foreign-tenant project IDs.
M-4: new test — show returns 200 for archived project (read preserved).
PHPStan baseline updated: 2 new test functions raise actingAs() count 7→9.
Tests: 9/9 passed (33 assertions). Larastan: 0 errors.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
I-1: scopeActive docblock — явное предупреждение что scope НЕ фильтрует
is_active; приостановленные проекты попадают; пример комбинирования.
I-2: migration down() — комментарий об асимметрии с up() и риске drift
с schema.sql v8.20 при случайном rollback.
M-1: archived_at перемещён в $fillable на позицию сразу после is_active
(lifecycle-state рядом с lifecycle-state, как указано в плане).
M-2: CHANGELOG header счётчик восемнадцать → девятнадцать записей.
Tests: ArchivedAtTest 2/2 PASS (4 assertions, 472 ms). No behavior change.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Spec для full-stack плана: backend CRUD на projects (POST/PATCH/DELETE/sync/bulk),
frontend ProjectsView с карточками+прогресс-баром, NewProjectDialog с 3 табами
(Site/Call/SMS), polling sync-статуса через setTimeout-recursion + backoff,
schema delta v8.19→v8.20 (projects.archived_at).
Через superpowers:brainstorming skill. 11-13 task'ов по vertical-slice TDD
(паттерн Plan 4). Self-review прошёл — 4 inline-фиксы внесены.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Plan-файл лежит в docs/superpowers/plans/, поэтому относительный путь
../../docs/Открытые_вопросы_v8_3.md резолвится в docs/docs/... (двойной docs).
Корректный путь — ../../Открытые_вопросы_v8_3.md (мы уже в docs/).
+ escape line 4536 (placeholder `(path)` в example-template) как code block,
чтобы lychee не трактовал как реальную ссылку.
CV gate Step 1: lychee 298/228 OK/0 Errors/70 Excluded.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
При InsufficientBalanceException в LedgerService::chargeForDelivery:
- DB::transaction откатывается (Deal/charge/balance не тронуты).
- Outer catch в createDealCopyForProject вызывает handleInsufficientBalance:
* UPDATE projects.is_active=false через pgsql_supplier (BYPASSRLS).
* Email ZeroBalancePausedMail через NotificationService::notifyZeroBalancePaused.
* Rate-limit 1/час/tenant через Redis SETNX (Cache::add).
* Log::warning с tenant_id/project_id/balance details.
- Возвращаем false (не rethrow), чтобы handle()-loop продолжал routing остальным tenant'ам.
5 тестов: project paused / email sent / rate-limit 1/h / 2nd email after 65min /
sharing-flow isolation (A paused, B receives).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Месячный cron-сброс tenants.delivered_in_month + projects.delivered_in_month
1-го числа каждого месяца в 00:00 МСК. Идёт через pgsql_supplier BYPASSRLS
connection (паттерн ResetDeliveredTodayCommand). Идемпотентный
(WHERE delivered_in_month <> 0 → повторный запуск 0 affected rows).
4 теста: reset multi-tenant + idempotency + Schedule registration +
BYPASSRLS without SET LOCAL.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- chk_lead_charges_prepaid_zero_price moved inline в CREATE TABLE lead_charges
(consistent с ~30 другими CHECK constraint'ами в schema.sql).
- LeadCharge.casts() — убран no-op 'charge_source' => 'string' (Eloquent
возвращает VARCHAR как string без cast'а; consistent с SupplierLead.platform).
- SchemaDeltaTest — добавлен uses(DatabaseTransactions::class) для tests 1+2
(rollback после теста, project convention LeadChargeTest/PricingTierTest).
- SchemaDeltaTest test #5 — замена destructive migrate:fresh на static parse
count(CREATE TABLE) / count(CREATE INDEX) / count(CREATE POLICY) в schema.sql.
Устраняет cross-test coupling в sequential pest run; параллельно убирает
LARAVEL_PARALLEL_TESTING skip — теперь все 5 тестов выполняются в parallel.
Метрики из static parse: 62 base tables / 117 indexes / 39 RLS policies
(совпадают с schema v8.19, spec §2.4).
All 5 SchemaDeltaTest assertions still pass. No new schema changes.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Plan 3 spec и plan markdown files (commits 1a265b5 + 989256b) используют
project-root-relative ссылки на проектные файлы (app/, db/, lefthook.yml).
GitHub UI рендерит их корректно; lychee local resolution через relative
fallback к markdown file directory ломается с 33 'file not found' errors.
Альтернативы:
- Переписать ~30 ссылок на ../../../ prefixes — overhead высокий
- Fix lychee --base/--root-dir не работает на multi-file batch с разной
глубиной vlozenii (docs/superpowers/specs/ vs docs/)
Это hygiene fix перед push merged main; pre-push lychee теперь pass.
Links валидируются вручную при review parent spec/plan.
Cause: pre-push lychee на git push origin main после merge supplier-sync-plan3.
Marker file for the new Claude Brain repository at c:/моя/проекты/claude-brain/.
Brain artifacts (CLAUDE.md / Pravila / Tooling / Plugin_stack_rules / hooks /
settings / plugin manifest / MCP templates) are now versioned independently
and synced into this project via:
cd c:/моя/проекты/claude-brain
./scripts/install.sh --target=<this-repo> --version=brain-vX.Y
Future edits to brain artifacts: edit in claude-brain repo, then re-run install.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 06:45:32 +03:00
876 changed files with 207299 additions and 4321 deletions
<!-- Canonical project-side ADR guide. Copied from the plugin's templates/adr-kit-guide.md to .claude/adr-kit-guide.md by /adr-kit:init, /adr-kit:upgrade, and /adr-kit:setup. -->
<!-- This file is plain markdown — readable by Claude Code, headless `claude -p`, shell scripts in pre-commit hooks, evaluator scripts, and any agent that doesn't process @-imports. Do not embed Claude-Code-specific syntax inside this file. -->
# ADR Kit Guide
This project uses [adr-kit](https://github.com/rvdbreemen/adr-kit) to manage Architecture Decision Records. The kit ships:
- a project-side guide (this file) referenced from `CLAUDE.md`,
- a library of slash commands and a subagent for ADR authorship,
- a pre-commit hook that catches code changes drifting outside accepted ADRs.
ADR files live at `docs/adr/ADR-NNN-kebab-case-title.md`. They are versioned, immutable once accepted, and the durable record of *why* the codebase looks the way it does.
## Three operating modes
| Mode | When | Entry point |
|---|---|---|
| **Init / bootstrap** | Once per project: scan source + docs, propose a starter ADR set, hook the kit into `CLAUDE.md`, install the pre-commit hook | `/adr-kit:init` |
| **Per-commit verification** | Every `git commit`: declarative-rule check **plus** Claude Sonnet LLM judge for `llm_judge: true` ADRs in one batched call. Default-on as of v0.13.0. Falls back to declarative-only when the `claude` CLI is unavailable | `.githooks/pre-commit` (auto) |
| **On-demand invocation** | Mid-session: write a new ADR, judge a staged diff, supersede an existing decision | `/adr-kit:adr`, `/adr-kit:judge`, `adr-generator` subagent |
| `/adr-kit:adr` | Author a single ADR (delegates to `adr-generator` subagent; runs four verification gates). | no — model can self-call |
| `/adr-kit:judge` | Interactive judge against a staged diff. Runs declarative checks + in-session LLM check for `llm_judge: true` ADRs. Walks resolution paths on violation. | no — model can self-call |
| `/adr-kit:lint` | Validate existing ADRs against the four verification gates. | yes |
| `/adr-kit:upgrade` | Migrate v0.11 → v0.12 footprint without re-running the heavy audit. | yes |
| `/adr-kit:install-hooks` | Install or uninstall the pre-commit hook. | yes |
## The four verification gates
An ADR cannot move from `Proposed` to `Accepted` until all four pass.
1.**Completeness** — every required section is present and non-empty: Status, Context, Decision, Alternatives Considered (≥ 2), Consequences (positive + negative), Related Decisions, References. Plus filename matches `ADR-NNN-kebab-case.md` and the heading number agrees.
2.**Evidence** — Context or References cites at least one concrete external/internal artefact (incident, profiling data, code path, RFC, vendor doc). No hand-waving justifications.
3.**Clarity** — Decision section names a single concrete choice (not a survey), uses imperative voice, no hedging language ("perhaps", "we should consider"). Identifiers (file paths, function names, config keys) are traceable.
4.**Consistency** — filename, heading number, and any cross-references resolve. No duplicate ADR numbers in the directory.
`bin/adr-lint` enforces Completeness and Consistency deterministically. Evidence and Clarity are heuristic; opt in via `--gates evidence,clarity` or run `/adr-kit:lint` to use the LLM-aware skill.
## Authoring workflow (`/adr-kit:adr` or `adr-generator`)
1. Identify the architecturally significant change (architecture, NFRs, interfaces, dependencies, build/CI tooling). Refactors and bug fixes within existing patterns do NOT need an ADR.
2. Invoke `/adr-kit:adr` (or the `adr-generator` subagent). Provide: title, context with concrete forces, ≥ 2 alternatives with rejection reasons, consequences (both directions), related ADRs.
3. The agent applies the four gates and writes `docs/adr/ADR-NNN-…md` with `Status: Proposed`.
4. Human review. Iterate until all gates pass.
5. Flip Status to `Accepted, YYYY-MM-DD` after explicit human approval. **Never self-approve.**
6. If the decision touches code in a mechanically expressible way, add an `Enforcement` block (see below) so the pre-commit hook can guard the boundary.
## Enforcement block (v0.12+)
Optional `## Enforcement` section at the end of an ADR. Fenced JSON code block, parsed by `bin/adr-judge`. Schema: plugin's `schemas/adr-enforcement.schema.json`.
-`forbid_pattern` — regex must NOT match any added line in the diff (lines starting with `+`, excluding `+++` markers).
-`forbid_import` — same engine as `forbid_pattern`; the separate name documents intent.
-`require_pattern` — regex must match at least once in the post-diff content of any file matching `path_glob`.
-`llm_judge: true` — Claude Sonnet evaluates the diff against this ADR's `## Decision` text at commit time (default-on as of v0.13.0). The pre-commit hook batches all `llm_judge: true` ADRs into one Sonnet call and blocks the commit on `VIOLATION`. Falls back gracefully (advisory only, exit 0) when the `claude` CLI is missing.
- ADRs with no Enforcement block are skipped silently by the judge.
**Path globs** support `**` (recursive). Examples: `src/**/*.py`, `tests/**`, `**/Makefile`.
## Pre-commit hook
After `/adr-kit:init` (or `/adr-kit:install-hooks`), every `git commit` runs `bin/adr-judge` on the staged diff with two passes:
- **Declarative pass** — fast, regex-only, no LLM. A violation exits non-zero and blocks the commit.
- **LLM pass (Sonnet, default-on as of v0.13.0)** — all `llm_judge: true` ADRs are batched into one `claude -p --model claude-sonnet-4-6` call. Sonnet returns a per-ADR JSON verdict; any `VIOLATION` blocks the commit with the model's one-sentence reason. Falls back gracefully when the `claude` CLI is missing or unauthenticated — never blocks a legitimate commit due to tooling drift.
**Cost shape** (typical project, 50 `llm_judge` ADRs, small diff): roughly $0.10–0.30 per commit on Sonnet 4.6 with prompt caching. Latency 5–10s. Configurable via `judge.llm_model` / `judge.llm_timeout_seconds` / `judge.llm_cmd` in `docs/adr/.adr-kit.json`.
Accepted ADRs are immutable. To change a decision:
1. Author a new ADR with the next number. Status `Proposed`. The Decision should explain what changes and why now.
2. In its Related Decisions: `Supersedes ADR-OLD`.
3. After the new ADR is `Accepted`: edit ONLY the old ADR's Status line to `Superseded by ADR-NEW, YYYY-MM-DD.` Leave every other section untouched — the old decision's content is the historical record.
Never edit Decision, Context, Consequences, or Alternatives of an Accepted/Deprecated ADR. The Status line is the only permitted change.
## Code review checks
When reviewing a PR, apply these seven checks (Check 7 added in v0.12):
1.**ADR exists** for any architecturally significant change in the PR (new dep, interface change, NFR shift, build tooling change). Missing → request the author to invoke `/adr-kit:adr` or `adr-generator`.
2.**ADR is linked** in the PR description (path or relative URL).
3.**No violation** of Accepted ADRs in the diff. Cross-reference against `docs/adr/README.md` and the Enforcement blocks. The pre-commit hook should have caught this; if it didn't, the ADR is missing rules or wasn't installed.
4.**Supersession chain is correct** — old ADR's Status updated, new ADR cross-references, content immutability preserved.
5.**All four gates pass** on any new/modified ADR. Cite the failing gate when blocking ("fails Evidence gate — no concrete reference in Context").
6.**Legacy non-compliance has a remediation plan** — pre-existing violations that this PR doesn't fix should at least carry a `// TODO(ADR-NNN): align` or a backlog entry, not be silently ignored.
7.**Enforcement block is set appropriately** on any new Accepted ADR with a code surface. Either declarative rules, OR `llm_judge: true`, OR an explicit "manual review only" note in the ADR body explaining why the rule cannot be expressed mechanically. Missing block on a code-touching ADR is a smell.
## Anti-rationalisation guards
When `/adr-kit:adr` is asked to write or accept an ADR, it actively pushes back on these nine common excuses (see plugin's `skills/adr/SKILL.md` for the full text):
- "It's just a small change" — the rule is "architecturally significant", not "large".
- "We can decide later" — later is now; defer = decide.
- "Everyone knows this" — undocumented tacit knowledge is the problem ADRs solve.
- "It's documented in the code" — code shows what, not why.
- "We'll do it the same as last time" — name "last time" with an ADR reference.
- "There's only one option" — there are always alternatives; "do nothing" is one.
- "It's reversible" — most architecture is partially reversible; the ADR captures the *current* commitment.
- "It's a refactor" — pure refactors don't need ADRs; *new patterns* introduced during refactoring do.
- "We don't have time" — opportunity cost of skipping is a future maintainer hunting for the why.
## Plugin-side deep dives
This guide is the project's own copy. For agents inside Claude Code, the plugin auto-loads richer instructions:
-`instructions/adr.coding.md` — per-developer rules (when to invoke the agent, supersession workflow, Definition of Done).
-`instructions/adr.review.md` — the seven review checks with citation templates.
-`skills/adr/SKILL.md` — full anti-rationalisation guard list, gate definitions, code examples.
-`agents/adr-generator.md` — the subagent prompt.
If you're working outside Claude Code (in a hook, a CI job, or a different agent), this file (`.claude/adr-kit-guide.md`) is your one-stop reference. Keep it in version control with the rest of the project.
Diagnose Pest 4 --parallel test failures in the Лидерра CRM project.
Classifies failures as (a) real failure, (b) quirk 72 (Redis supplier:session
race в subdir-only), (c) quirk 73 (cumulative state on long sessions),
(d) quirk 77 (unique-key collision в bulk-action tests with Faker-generated names),
or (e) other — escalate. Falsifies hypotheses with actual command runs.
tools: Read, Grep, Bash
---
# Pest --parallel debugger agent — Лидерра
You are diagnosing a Pest 4 --parallel test failure in the Лидерра CRM project. Read-only diagnosis; recommend fixes, do not apply them.
## Known quirks (from memory feedback_environment.md, verified 2026-05-13)
1.**Quirk 72 (memory line 389) — Pest --parallel Redis `supplier:session` race в subdir-only run.**
- Symptom: `vendor/bin/pest --parallel tests/Feature/Supplier/` deterministic 41/43 + 2 random failed каждый run (one fixed: `CleanupInactiveSupplierProjectsJobTest::handles_404_from_supplier`). Single-file isolated 8/8 passes.
- Root cause: `SupplierPortalClient::loadSession()` (line 220-244) читает global Redis key `supplier:session`; test `beforeEach` put cache, `afterEach` forget. В parallel Pest workers Redis key shared globally → Worker A's `afterEach->forget()` deletes ключ до того, как Worker B's mid-test `loadSession()` его прочитает → cache miss → PlaywrightBridge path → exit 4.
- Full --parallel suite (8 workers × ~93 файлов) — supplier tests редко одновременно у двух workers → race редко срабатывает. Full passes 742/739/0/3 ✅.
- Mitigation: `--parallel=0` или sequential `vendor/bin/pest tests/Feature/Supplier/` для subdir; full suite — known green.
2.**Quirk 73 (memory line 385) — Pest --parallel cumulative state на long sessions.**
- Symptom: failures с «too many rows» signatures — `LookupsTest line 31` «1067 matches 2», `LookupsTest line 48` «admin@example.ru vs Абрам К.», `ProjectExtensionsTest line 89` «7677 identical to 1».
- Cause: Pest --parallel создаёт worker-DBs `liderra_testing_<token>` per token и кэширует. Migrations не пересоздаются между runs без `--recreate-databases`. Tests используют `DatabaseTransactions` (не `RefreshDatabase` — `Pest.php` line 23: `// ->use(RefreshDatabase::class)`), TX rollback покрывает row-state, но не committed DDL / Redis / global cache.
- Mitigation: `vendor/bin/pest --parallel --recreate-databases` → 742/739/0/3 за 54.9s. `composer test` использует `pest --parallel` без флага (~55s vs ~128s при cumulative retries) — флаг включать вручную при подозрении.
3.**Quirk 77 (memory feedback_environment.md, added 13.05.2026 day +1) — Pest --parallel deterministic unique-key collision на `projects(tenant_id, name)` в bulk-action tests.**
- Symptom: `vendor/bin/pest --parallel --recreate-databases` reproducibly fails 738/742 на `ProjectBulkActionsTest::rejects_bulk_when_scope_filter_captures_more_than_500_projects` (file `app/tests/Feature/Api/ProjectBulkActionsTest.php:194-206`). Signature `SQLSTATE[23505] projects_tenant_id_name_key — (tenant_id, name)=(<id>, "<faker-3words>")`. Tenant_id varies per run (~50 apart — per-worker auto-increment).
- Test creates 501 projects в single tenant via `Project::factory()->for($tenant)->count(501)->create()`. ProjectFactory.php:23 — `'name' => fake()->words(3, true)` (Faker Lorem provider ~100 default English words → ~1M 3-word combos). Birthday paradox math для 501 samples из ~1M combos → ~12.5% per-test failure probability — НЕ deterministic в isolation. Reproducible-in-parallel-but-not-sequential pattern suggests worker state sharing (shared Faker seed via PHP global state? Eloquent factory caching?). Full RCA pending.
- Sequential `vendor/bin/pest tests/Feature/Api/ProjectBulkActionsTest.php` passes 14/14 ✅. Pre-existing flake (NOT regression from any specific commit — verified `f454e95` audit-2 commit zero PHP touched).
- Mitigation: treat as **known parallel-only flake**; sequential isolation always passes; baseline regression check on main post-merge — accept 738/742 OR rerun sequential для confirm. Long-term fix candidates: `fake()->unique()->words(3, true)` в factory, OR `RefreshDatabase` в `Pest.php` line 18, OR explicit Faker seed per-test.
**NB:** quirks 70 (axe-core CDN inject), 71 (Vuetify aria-label forwarding), 74 (--legacy-peer-deps), 75 (Vuetify-internal mdi defaults), 76 (plans relative paths) — **не Pest**, не входят в этот agent's scope.
## Diagnostic pipeline
Given a failure output (paste from user OR capture from `./vendor/bin/pest --parallel`):
1.**Capture exact failure.** Какой test file:line failed? Assertion message?
2.**Hypothesis 1 — real failure.** Read failing test + production code. Catches real bug? If yes — fix the code.
3.**Hypothesis 2 — quirk 72 (Redis `supplier:session` race).** Failing test в `tests/Feature/Supplier/*`? Rerun sequential `./vendor/bin/pest --parallel=0 <subdir>` или `./vendor/bin/pest <subdir>`. If passes — race. Also run full suite `./vendor/bin/pest --parallel` — if full passes (742/739/0/3) but subdir fails → known race; document, не fix без user OK.
4.**Hypothesis 3 — quirk 73 (cumulative state).** Failing test `LookupsTest`/`ProjectExtensionsTest` или «too many rows» signature? Rerun `./vendor/bin/pest --parallel --recreate-databases`. If passes → cumulative; baseline restored.
5.**Hypothesis 4 — quirk 77 (unique-key collision в bulk-action tests).** Failing test creates ≥500 records of one model в single tenant с Faker-generated unique field? Pattern: `SQLSTATE[23505]` + `_tenant_id_<col>_key` constraint name + Faker-style value в DETAIL. Rerun sequential `./vendor/bin/pest <test-file>` — if passes 14/14 → quirk 77 confirmed; document as known parallel-only flake, не fix без user OK (root cause не fully RCA'd).
6.**Hypothesis 5 — other.** If none of above → escalate с raw output + tested hypotheses + outcome per hypothesis.
For manually checking a single named table before commit - use the /rls-check skill.
tools: Read, Grep, Glob, Bash
---
# RLS reviewer agent — Лидерра
You are reviewing a database migration or schema change for RLS (Row-Level Security) compliance in the Лидерра CRM project. Read-only review — DO NOT edit files.
## Контекст проекта
PostgreSQL 16 с 5 ролями (db/00_create_roles.sql + db/02_grants.sql):
1.`crm_app_user` — regular tenant user; RLS enforced via `current_setting('app.current_tenant_id')`.
3.`crm_supplier_worker` — SaaS-level worker (BYPASSRLS) для supplier integration jobs.
4.`crm_readonly` — read-only для reports; RLS enforced.
5.`crm_migrator` — DDL role для Laravel migrations; RLS bypassed via session.
Каждая tenant-scoped таблица должна иметь:
-`tenant_id UUID NOT NULL REFERENCES tenants(id)` колонка.
-`ALTER TABLE <name> ENABLE ROW LEVEL SECURITY;`.
- Минимум 2 политики: SELECT (tenant scope `tenant_id = current_setting('app.current_tenant_id')::uuid`), ALL (admin scope).
- GRANT'ы для 5 ролей в `db/02_grants.sql`.
SaaS-level таблицы (e.g., `supplier_csv_reconcile_log`, `system_settings`) exempt от tenant_id; должны иметь explicit `-- SaaS-level` comment.
Каждое schema change требует записи в `db/CHANGELOG_schema.md` (CLAUDE.md §5 п.8).
## Граница со скилом /rls-check
`rls-reviewer` (этот агент) и скил `/rls-check`
(`.claude/skills/rls-check/SKILL.md`) оба проверяют RLS. Правило выбора:
- Есть diff / ветка / PR с изменениями БД, набор таблиц заранее не известен →
**этот агент**.
- Знаешь имя одной конкретной таблицы, проверка вручную перед коммитом →
**скил `/rls-check <table>`**.
Этот агент прогоняет **7 статических пунктов** чеклиста. Живой дымовой тест
(`pest --filter RlsSmokeTest`) намеренно **не входит** в агентский чеклист:
запуск Pest в ревью-субагенте медленный и задевает гонки `--parallel`
(квирки 72/77, см. `.claude/agents/pest-parallel-debugger.md`). Живой дымовой
тест — 8-я строка скила `/rls-check`. 7 пунктов агента === первые 7 строк
вывода скила (общее статическое ядро).
## Workflow
1. Read target migration файл OR `db/schema.sql` diff (use `git diff HEAD~1 -- db/schema.sql` или указанные изменения).
2. Для каждой added/modified таблицы — run 7-item checklist:
- tenant_id column (или SaaS-level comment).
- ENABLE RLS.
- SELECT policy для crm_app_user.
- ALL policy для crm_app_admin (или per-convention).
- 5-role GRANTs в db/02_grants.sql.
- db/CHANGELOG_schema.md entry.
- squawk passes (`./bin/squawk.exe <file>`).
3. Cross-check `db/02_grants.sql` для matching GRANTs.
4. Cross-check `db/CHANGELOG_schema.md` для entry.
5. Run `./bin/squawk.exe db/schema.sql 2>&1 | tail -10` и capture issues.
6. Output structured report:
```text
RLS Review — <table_name>
[✅/❌] tenant_id column present
[✅/❌] ENABLE ROW LEVEL SECURITY
[✅/❌] SELECT policy for crm_app_user
[✅/❌] ALL policy for crm_app_admin
[✅/❌] 5-role GRANTs in db/02_grants.sql
[✅/❌] db/CHANGELOG_schema.md entry
[✅/❌] squawk passes (0 issues)
Issues:
- <file>:<line>:<col> <message>
Pass: <N>/7
```
## Constraints
- READ-ONLY — не edit files, только report.
- Falsify с actual command runs, не speculate.
- SaaS-level exemption — accept если explicit comment present; flag если comment отсутствует.
- Partitioned tables (e.g., `lead_charges` partitioned by month) — verify policy применяется к parent + children.
## Out of scope
- General SQL style (squawk handles).
- Business logic review (other agents).
- Performance review (separate concern).
- Проверка одной названной таблицы вручную перед коммитом + живой дымовой
тест — сценарий скила `/rls-check`, не агента.
## Verification protocol
Каждое утверждение про код — с `file:line` как pin'ом. "Looks correct" / "should pass" — запрещено. Только "passed with command X — output Y" or "failed with command X — output Y".
description: Complete a security review of the pending changes on the current branch
---
You are a senior security engineer conducting a focused security review of the changes on this branch.
GIT STATUS:
```
!`git status`
```
FILES MODIFIED:
```
!`git diff --name-only origin/HEAD...`
```
COMMITS:
```
!`git log --no-decorate origin/HEAD...`
```
DIFF CONTENT:
```
!`git diff --merge-base origin/HEAD`
```
Review the complete diff above. This contains all code changes in the PR.
OBJECTIVE:
Perform a security-focused code review to identify HIGH-CONFIDENCE security vulnerabilities that could have real exploitation potential. This is not a general code review - focus ONLY on security implications newly added by this PR. Do not comment on existing security concerns.
CRITICAL INSTRUCTIONS:
1. MINIMIZE FALSE POSITIVES: Only flag issues where you're >80% confident of actual exploitability
3. FOCUS ON IMPACT: Prioritize vulnerabilities that could lead to unauthorized access, data breaches, or system compromise
4. EXCLUSIONS: Do NOT report the following issue types:
- Denial of Service (DOS) vulnerabilities, even if they allow service disruption
- Secrets or sensitive data stored on disk (these are handled by other processes)
- Rate limiting or resource exhaustion issues
SECURITY CATEGORIES TO EXAMINE:
**Input Validation Vulnerabilities:**
- SQL injection via unsanitized user input
- Command injection in system calls or subprocesses
- XXE injection in XML parsing
- Template injection in templating engines
- NoSQL injection in database queries
- Path traversal in file operations
**Authentication & Authorization Issues:**
- Authentication bypass logic
- Privilege escalation paths
- Session management flaws
- JWT token vulnerabilities
- Authorization logic bypasses
**Crypto & Secrets Management:**
- Hardcoded API keys, passwords, or tokens
- Weak cryptographic algorithms or implementations
- Improper key storage or management
- Cryptographic randomness issues
- Certificate validation bypasses
**Injection & Code Execution:**
- Remote code execution via deseralization
- Pickle injection in Python
- YAML deserialization vulnerabilities
- Eval injection in dynamic code execution
- XSS vulnerabilities in web applications (reflected, stored, DOM-based)
**Data Exposure:**
- Sensitive data logging or storage
- PII handling violations
- API endpoint data leakage
- Debug information exposure
Additional notes:
- Even if something is only exploitable from the local network, it can still be a HIGH severity issue
ANALYSIS METHODOLOGY:
Phase 1 - Repository Context Research (Use file search tools):
- Identify existing security frameworks and libraries in use
- Look for established secure coding patterns in the codebase
- Examine existing sanitization and validation patterns
- Understand the project's security model and threat model
Phase 2 - Comparative Analysis:
- Compare new code changes against existing security patterns
- Identify deviations from established secure practices
- Look for inconsistent security implementations
- Flag code that introduces new attack surfaces
Phase 3 - Vulnerability Assessment:
- Examine each modified file for security implications
- Trace data flow from user inputs to sensitive operations
- Look for privilege boundaries being crossed unsafely
- Identify injection points and unsafe deserialization
REQUIRED OUTPUT FORMAT:
You MUST output your findings in markdown. The markdown output should contain the file, line number, severity, category (e.g. `sql_injection` or `xss`), description, exploit scenario, and fix recommendation.
For example:
# Vuln 1: XSS: `foo.py:42`
- Severity: High
- Description: User input from `username` parameter is directly interpolated into HTML without escaping, allowing reflected XSS attacks
- Exploit Scenario: Attacker crafts URL like `/bar?q=<script>alert(document.cookie)</script>` to execute JavaScript in victim's browser, enabling session hijacking or data theft
- Recommendation: Use Flask's escape() function or Jinja2 templates with auto-escaping enabled for all user inputs rendered in HTML
SEVERITY GUIDELINES:
- **HIGH**: Directly exploitable vulnerabilities leading to RCE, data breach, or authentication bypass
- **MEDIUM**: Vulnerabilities requiring specific conditions but with significant impact
- **LOW**: Defense-in-depth issues or lower-impact vulnerabilities
CONFIDENCE SCORING:
- 0.9-1.0: Certain exploit path identified, tested if possible
- 0.8-0.9: Clear vulnerability pattern with known exploitation methods
- 0.7-0.8: Suspicious pattern requiring specific conditions to exploit
- Below 0.7: Don't report (too speculative)
FINAL REMINDER:
Focus on HIGH and MEDIUM findings only. Better to miss some theoretical issues than flood the report with false positives. Each finding should be something a security engineer would confidently raise in a PR review.
FALSE POSITIVE FILTERING:
> You do not need to run commands to reproduce the vulnerability, just read the code to determine if it is a real vulnerability. Do not use the bash tool or write to any files.
>
> HARD EXCLUSIONS - Automatically exclude findings matching these patterns:
>
> 1. Denial of Service (DOS) vulnerabilities or resource exhaustion attacks.
> 2. Secrets or credentials stored on disk if they are otherwise secured.
> 3. Rate limiting concerns or service overload scenarios.
> 4. Memory consumption or CPU exhaustion issues.
> 5. Lack of input validation on non-security-critical fields without proven security impact.
> 6. Input sanitization concerns for GitHub Action workflows unless they are clearly triggerable via untrusted input.
> 7. A lack of hardening measures. Code is not expected to implement all security best practices, only flag concrete vulnerabilities.
> 8. Race conditions or timing attacks that are theoretical rather than practical issues. Only report a race condition if it is concretely problematic.
> 9. Vulnerabilities related to outdated third-party libraries. These are managed separately and should not be reported here.
> 10. Memory safety issues such as buffer overflows or use-after-free-vulnerabilities are impossible in rust. Do not report memory safety issues in rust or any other memory safe languages.
> 11. Files that are only unit tests or only used as part of running tests.
> 12. Log spoofing concerns. Outputting un-sanitized user input to logs is not a vulnerability.
> 13. SSRF vulnerabilities that only control the path. SSRF is only a concern if it can control the host or protocol.
> 14. Including user-controlled content in AI system prompts is not a vulnerability.
> 15. Regex injection. Injecting untrusted content into a regex is not a vulnerability.
> 16. Regex DOS concerns.
> 17. Insecure documentation. Do not report any findings in documentation files such as markdown files.
> 18. A lack of audit logs is not a vulnerability.
>
> PRECEDENTS -
>
> 1. Logging high value secrets in plaintext is a vulnerability. Logging URLs is assumed to be safe.
> 2. UUIDs can be assumed to be unguessable and do not need to be validated.
> 3. Environment variables and CLI flags are trusted values. Attackers are generally not able to modify them in a secure environment. Any attack that relies on controlling an environment variable is invalid.
> 4. Resource management issues such as memory or file descriptor leaks are not valid.
> 5. Subtle or low impact web vulnerabilities such as tabnabbing, XS-Leaks, prototype pollution, and open redirects should not be reported unless they are extremely high confidence.
> 6. React and Angular are generally secure against XSS. These frameworks do not need to sanitize or escape user input unless it is using dangerouslySetInnerHTML, bypassSecurityTrustHtml, or similar methods. Do not report XSS vulnerabilities in React or Angular components or tsx files unless they are using unsafe methods.
> 7. Most vulnerabilities in github action workflows are not exploitable in practice. Before validating a github action workflow vulnerability ensure it is concrete and has a very specific attack path.
> 8. A lack of permission checking or authentication in client-side JS/TS code is not a vulnerability. Client-side code is not trusted and does not need to implement these checks, they are handled on the server-side. The same applies to all flows that send untrusted data to the backend, the backend is responsible for validating and sanitizing all inputs.
> 9. Only include MEDIUM findings if they are obvious and concrete issues.
> 10. Most vulnerabilities in ipython notebooks (*.ipynb files) are not exploitable in practice. Before validating a notebook vulnerability ensure it is concrete and has a very specific attack path where untrusted input can trigger the vulnerability.
> 11. Logging non-PII data is not a vulnerability even if the data may be sensitive. Only report logging vulnerabilities if they expose sensitive information such as secrets, passwords, or personally identifiable information (PII).
> 12. Command injection vulnerabilities in shell scripts are generally not exploitable in practice since shell scripts generally do not run with untrusted user input. Only report command injection vulnerabilities in shell scripts if they are concrete and have a very specific attack path for untrusted input.
>
> SIGNAL QUALITY CRITERIA - For remaining findings, assess:
>
> 1. Is there a concrete, exploitable vulnerability with a clear attack path?
> 2. Does this represent a real security risk vs theoretical best practice?
> 3. Are there specific code locations and reproduction steps?
> 4. Would this finding be actionable for a security team?
>
> For each finding, assign a confidence score from 1-10:
>
> - 1-3: Low confidence, likely false positive or noise
> - 4-6: Medium confidence, needs investigation
> - 7-10: High confidence, likely true vulnerability
PROJECT FALSE-POSITIVE GUIDANCE (Лидерра):
> This section is project-specific (Лидерра CRM — Laravel 13 + Vue 3 multi-tenant SaaS).
> Apply it alongside the HARD EXCLUSIONS and PRECEDENTS above when filtering findings.
>
> EXPECTED — treat as NOT a finding:
>
> 1. Missing application-layer tenant checks where the table has PostgreSQL Row-Level
> Security. Tenant isolation is enforced at the DB layer (`SET LOCAL
> app.current_tenant_id` via the `SetTenantContext` middleware; 5 DB roles; 39 RLS
> policies — see `docs/adr/ADR-002-multitenancy-postgres-rls.md`). DO still flag
> queued jobs or code running as the `crm_supplier_worker` role (which is BYPASSRLS)
> that read/write tenant-scoped tables WITHOUT an explicit `where('tenant_id', ...)`.
> 2. The `tools/*.mjs` economy / ruflo hook scripts using `child_process.spawnSync`
> or `process.env`. These are intentional local CLI hooks, not user-facing or
1. Use a sub-task to identify vulnerabilities. Use the repository exploration tools to understand the codebase context, then analyze the PR changes for security implications. In the prompt for this sub-task, include all of the above.
2. Then for each vulnerability identified by the above sub-task, create a new sub-task to filter out false-positives. Launch these sub-tasks as parallel sub-tasks. In the prompt for these sub-tasks, include everything in the "FALSE POSITIVE FILTERING" instructions (including the "PROJECT FALSE-POSITIVE GUIDANCE (Лидерра)" block).
3. Filter out any vulnerabilities where the sub-task reported a confidence less than 8.
Your final reply must contain the markdown report and nothing else.
"command":"node -e \"const f=process.env.CLAUDE_FILE_PATH||''; const pd=process.env.CLAUDE_PROJECT_DIR||''; const path=require('path'); if (f && pd && path.resolve(f) === path.resolve(pd, 'CLAUDE.md')) { process.stderr.write('\\n[hook] WARNING: Direct edit of root CLAUDE.md detected. Per CLAUDE.md §5 п.10, prefer /claude-md-management:revise-claude-md or /claude-md-management:claude-md-improver. If invoked via that skill, this warning is informational.\\n'); }\""
"command":"node -e \"const f=process.env.CLAUDE_FILE_PATH||''; const n=f.replace(/\\\\\\\\/g,'/'); if (/(^|\\\\/)db\\\\/schema\\\\.sql$/i.test(n)) { process.stdout.write('\\n[hook] REMINDER: You modified db/schema.sql. Per CLAUDE.md §5 п.8, add a corresponding entry to db/CHANGELOG_schema.md before committing.\\n'); }\""
description: Use ONCE PER SPRINT (or by explicit user invocation "брейн-ретро") to aggregate evidence from docs/observer/episodes-*.jsonl + notes/*.md and propose regulatory candidates. Read-only — never edits Tooling/Pravila/PSR_v1 automatically; only proposes.
---
# Brain Retro
Aggregator over observer evidence. Reads JSONL + optional MD notes, surfaces candidates for normative updates. User decides what to apply.
## When to invoke
- Explicit user request: «брейн-ретро» / «сделай brain-retro» / `/brain-retro`.
- Periodic — owner discretion (e.g. end of sprint).
- NOT auto-invoked.
## What it does NOT do
- Does NOT edit `docs/Tooling_v8_3.md`, `docs/Pravila_raboty_Claude_v1_1.md`, `docs/Plugin_stack_rules_v1.md`, `CLAUDE.md`, or any normative file.
- Does NOT write to `docs/observer/episodes-*.jsonl` (read-only).
- Does NOT trigger automatic memory updates.
## Procedure
1.**Determine period**: ask user «за какой период» or default to «since last brain-retro» (find latest `docs/observer/notes/YYYY-MM-DD-brain-retro-*.md`).
2.**Read evidence**: glob `docs/observer/episodes-YYYY-MM.jsonl` for the period; read all lines as JSON.
3.**Read optional notes**: glob `docs/observer/notes/*.md` filtered by date.
4.**Update read-counter**: bump `docs/observer/.read-counter.json``last_read_at` to now, increment `read_count_last_period`. (Side-effect — used by C3 observer-of-observer.)
5.**Run the deterministic analyzer**: `node tools/brain-retro-analyzer.mjs docs/observer/episodes-YYYY-MM.jsonl` (pass every monthly file in the period). It returns JSON with `episodeCount`, `observerErrorCount`, `tasks` (episodes grouped into tasks), `causalChains` (error→fix candidates) and `factorMatrix` (outcome distribution per factor). The analyzer deduplicates the routing-gate double-write and infers the true `outcome` of each episode from the next episode's `prompt_signal` — never trust the stored `outcome` (it is `unknown` at write time).
6.**Aggregate** per `references/aggregation-template.md` — fill the Factor analysis matrix from the analyzer's `factorMatrix`, the task groups from `tasks`, the causal-chain candidates from `causalChains`.
7.**Propose candidates** — clearly separated section «Candidates for owner review». Each candidate has rationale + suggested edit + rejection-option.
8.**Save retro note**: `docs/observer/notes/YYYY-MM-DD-brain-retro.md` with full aggregation.
9.**Report to user**: high-signal summary.
## Output anatomy
See `references/aggregation-template.md`.
## Behavioral rule reminders
- **«Не использован ≠ проблема»** — when reporting node usage counts, NEVER mark unused nodes as «zombie» / «removal candidate». Cite `memory/feedback_brain_unused_tools_not_problem.md`.
- **No auto-edit** — every regulatory suggestion is a candidate, not an action.
- **Type**: new canonical chain L13+ / new ADR / boundary clarification / etc.
- **Evidence**: refs to JSONL lines (file:line).
- **Suggested action**: `<concrete edit>`.
- **Cost / risk**: `<brief>`.
(repeat for each candidate; could be 0)
## Informational metrics (NOT alerts)
- Nodes used at least once this period: K / 60+
- Nodes never used since beginning of observer logs: L / 60+ — **not a problem** per [feedback_brain_unused_tools_not_problem](../../../memory/feedback_brain_unused_tools_not_problem.md)
description: "CCPM - spec-driven project management: PRD → Epic → GitHub Issues → parallel agents → shipped code. Use this skill for anything in the software delivery lifecycle: writing a PRD ('write a PRD for X', 'let's plan X', 'scope this out'), parsing a PRD into an epic, decomposing an epic into tasks, syncing to GitHub ('sync the X epic', 'push tasks to github'), starting work on an issue ('start working on issue N', 'let's work on issue N'), analyzing parallel work streams, running standups ('standup', 'run the standup'), checking status ('what's next', 'what's blocked', 'what are we working on'), closing issues, or merging an epic. Use ccpm any time the user is talking about shipping a feature, managing work, or tracking progress — even if they don't say 'ccpm' or 'PRD'. Do NOT use for: debugging code, writing tests, reviewing PRs, or raw GitHub issue/PR operations with no delivery context."
---
# CCPM - Claude Code Project Manager
A spec-driven development workflow: PRD → Epic → GitHub Issues → Parallel Agents → Shipped Code.
## Core Philosophy
Requirements live in files, not heads. Every feature starts as a PRD, becomes a technical epic, decomposes into GitHub issues, and gets executed by parallel agents with full traceability.
## File Conventions
Before doing anything, read `references/conventions.md` for path standards, frontmatter schemas, and GitHub operation rules. These apply to all phases.
## The Five Phases
### 1. Plan — Capture requirements
**When**: User wants to define a new feature, product requirement, or scope of work.
**Read**: `references/plan.md`
**Covers**: Writing PRDs through guided brainstorming, converting PRDs to technical epics.
### 2. Structure — Break it down
**When**: An epic exists and needs to be decomposed into concrete tasks.
**Read**: `references/structure.md`
**Covers**: Epic decomposition into numbered task files with dependencies and parallelization.
### 3. Sync — Push to GitHub
**When**: Local epic/tasks need to become GitHub issues, progress needs to be posted as comments, or a bug is found and needs a linked issue created.
**When**: User asks for status, standup report, what's blocked, what's next, or needs to validate state.
**Read**: `references/track.md`
**Covers**: Status, standup, search, in-progress, next priority, blocked items, validation.
---
## Script-First Rule
For deterministic operations — anything that reads and reports without needing reasoning — always run the bash script directly rather than doing the work manually:
| What the user wants | Script to run |
|---|---|
| Project status | `bash references/scripts/status.sh` |
This phase turns an idea into a structured PRD, then converts the PRD into a technical epic ready for decomposition.
---
## Writing a PRD
**Trigger**: User wants to plan a new feature, product requirement, or area of work.
### Preflight
- Check if `.claude/prds/<name>.md` already exists — if so, confirm overwrite before proceeding.
- Ensure `.claude/prds/` directory exists; create it if not.
- Feature name must be kebab-case (lowercase, letters/numbers/hyphens, starts with a letter). If not: "❌ Feature name must be kebab-case. Example: user-auth, payment-v2"
### Process
Conduct a genuine brainstorming session before writing anything. Ask the user:
- What problem does this solve?
- Who are the users affected?
- What does success look like?
- What's explicitly out of scope?
- What are the constraints (tech, time, resources)?
Then write `.claude/prds/<name>.md` with this frontmatter and structure:
```markdown
---
name: <feature-name>
description: <one-line summary>
status: backlog
created: <run: date -u +"%Y-%m-%dT%H:%M:%SZ">
---
# PRD: <feature-name>
## Executive Summary
## Problem Statement
## User Stories
## Functional Requirements
## Non-Functional Requirements
## Success Criteria
## Constraints & Assumptions
## Out of Scope
## Dependencies
```
**Quality gates before saving:**
- No placeholder text in any section
- User stories include acceptance criteria
- Success criteria are measurable
- Out of scope is explicitly listed
**After creation**: Confirm "✅ PRD created: `.claude/prds/<name>.md`" and suggest: "Ready to create technical epic? Say: parse the <name> PRD"
---
## Parsing a PRD into a Technical Epic
**Trigger**: User wants to convert an existing PRD into a technical implementation plan.
- Check if `.claude/epics/<name>/epic.md` already exists — confirm overwrite if so.
### Process
Read the PRD fully, then produce `.claude/epics/<name>/epic.md`:
```markdown
---
name: <feature-name>
status: backlog
created: <run: date -u +"%Y-%m-%dT%H:%M:%SZ">
progress: 0%
prd: .claude/prds/<name>.md
github: (will be set on sync)
---
# Epic: <feature-name>
## Overview
## Architecture Decisions
## Technical Approach
### Frontend Components
### Backend Services
### Infrastructure
## Implementation Strategy
## Task Breakdown Preview
## Dependencies
## Success Criteria (Technical)
## Estimated Effort
```
**Key constraints:**
- Aim for ≤10 tasks total — prefer simplicity over completeness.
- Look for ways to leverage existing functionality before creating new code.
- Identify parallelization opportunities in the task breakdown preview.
**After creation**: Confirm "✅ Epic created: `.claude/epics/<name>/epic.md`" and suggest: "Ready to decompose into tasks? Say: decompose the <name> epic"
---
## Editing a PRD or Epic
Read the file first, make targeted edits preserving all frontmatter. Update the `updated` frontmatter field with current datetime.
This phase converts a technical epic into concrete, numbered task files with dependency and parallelization metadata.
---
## Epic Decomposition
**Trigger**: User wants to break an epic into actionable tasks.
### Preflight
- Verify `.claude/epics/<name>/epic.md` exists with valid frontmatter.
- If numbered task files (001.md, 002.md...) already exist in the epic directory, list them and confirm deletion before recreating.
- If epic status is "completed", warn the user before proceeding.
### Process
Read the epic fully. Analyze for parallelism — which pieces of work can happen simultaneously without file conflicts?
**Task types to consider:**
- Setup: environment, scaffolding, dependencies
- Data: models, schemas, migrations
- API: endpoints, services, integration
- UI: components, pages, styling
- Tests: unit, integration, e2e
- Docs: README, API docs, changelogs
**Parallelization strategy by epic size:**
- Small (<5 tasks): create sequentially
- Medium (5–10 tasks): batch into 2–3 groups, spawn parallel Task agents
- Large (>10 tasks): analyze dependencies first, launch parallel agents (max 5 concurrent), create dependent tasks after prerequisites
For parallel creation, use the Task tool:
```yaml
Task:
description: "Create task files batch N"
subagent_type: "general-purpose"
prompt: |
Create task files for epic: <name>
Tasks to create: [list 3-4 tasks]
Save to: .claude/epics/<name>/001.md, 002.md, etc.
Follow the task file format exactly.
Return: list of files created.
```
### Task File Format
```markdown
---
name: <Task Title>
status: open
created: <run: date -u +"%Y-%m-%dT%H:%M:%SZ">
updated: <same as created>
github: (will be set on sync)
depends_on: []
parallel: true
conflicts_with: []
---
# Task: <Task Title>
## Description
## Acceptance Criteria
- [ ]
## Technical Details
## Dependencies
## Effort Estimate
- Size: XS/S/M/L/XL
- Hours: N
## Definition of Done
- [ ] Code implemented
- [ ] Tests written and passing
- [ ] Code reviewed
```
**Numbering**: sequential 001.md, 002.md, etc. Tasks are renamed to GitHub issue numbers after sync — do not hard-code dependencies by filename, use the `depends_on` array.
### After Creating All Tasks
Append a summary to the epic file:
```markdown
## Tasks Created
- [ ] 001.md - <Title> (parallel: true/false)
- [ ] 002.md - <Title> (parallel: true/false)
Total tasks: N
Parallel tasks: N
Sequential tasks: N
Estimated total effort: N hours
```
**After completion**: Confirm "✅ Created N tasks for epic: <name>" and suggest: "Ready to push to GitHub? Say: sync the <name> epic"
---
## Dependency Rules
- `depends_on` lists task numbers that must complete before this task can start.
- `parallel: true` means the task can run concurrently with others it doesn't conflict with.
- `conflicts_with` lists tasks that touch the same files — these cannot run in parallel.
- Circular dependencies are an error — check before finalizing.
REPO=$(echo "$remote_url" | sed 's|.*github.com[:/]||' | sed 's|\.git$||')
```
---
## Epic Sync — Push Epic + Tasks to GitHub
**Trigger**: User wants to push a local epic and its tasks to GitHub as issues.
### Preflight
- Verify `.claude/epics/<name>/epic.md` exists.
- Verify numbered task files exist — if none: "❌ No tasks to sync. Decompose the epic first."
### Process
**Step 1 — Create epic issue:**
Strip frontmatter from epic.md, then:
```bash
sed '1,/^---$/d; 1,/^---$/d' .claude/epics/<name>/epic.md > /tmp/epic-body.md
epic_number=$(gh issue create \
--repo "$REPO" \
--title "Epic: <name>" \
--body-file /tmp/epic-body.md \
--label "epic,epic:<name>,feature" \
--json number -q .number)
```
**Step 2 — Create task sub-issues:**
Check if `gh-sub-issue` extension is available:
```bash
if gh extension list | grep -q "yahsan2/gh-sub-issue"; then
use_subissues=true
fi
```
For <5 tasks: create sequentially.
For ≥5 tasks: use parallel Task agents (3-4 tasks per batch).
Per task:
```bash
sed '1,/^---$/d; 1,/^---$/d' <task_file> > /tmp/task-body.md
task_number=$(gh issue create \
--repo "$REPO" \
--title "<task_name>" \
--body-file /tmp/task-body.md \
--label "task,epic:<name>" \
--json number -q .number)
# or with sub-issues:
# gh sub-issue create --parent $epic_number ...
```
**Step 3 — Rename task files and update references:**
After all issues are created, rename `001.md` → `<issue_number>.md` and update all `depends_on`/`conflicts_with` arrays to use real issue numbers (not sequential numbers).
```bash
# Build old→new mapping, then for each task file:
sed -i.bak "s/\b001\b/<new_num_1>/g" <file> # repeat for each mapping
mv 001.md <new_num>.md
```
**Step 4 — Update frontmatter:**
```bash
current_date=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
# Update github: and updated: fields in epic.md and each task file
gh issue close $epic_issue -c "Epic completed and merged to main"
```
Update epic.md frontmatter: `status: completed`.
---
## Reporting a Bug Against a Completed Issue
**Trigger**: User finds a bug while testing a completed or in-progress issue — e.g. "found a bug in issue 42", "email validation is broken, came up while testing issue 42".
The workflow should stay automated: create a linked bug task without losing context from the original issue.
If a script fails or the output needs interpretation (e.g., an error in the output, or the user asks "what does this mean"), then step in to explain. But always run the script first — don't guess at what status/standup output would look like.
If `.claude/` directory doesn't exist at all, the project hasn't been initialized. Direct the user to run:
description: Expert data scientist for advanced analytics, machine learning, and statistical modeling. Handles complex data analysis, predictive modeling, and business intelligence.
---
## Use this skill when
- Working on data scientist tasks or workflows
- Needing guidance, best practices, or checklists for data scientist
## Do not use this skill when
- The task is unrelated to data scientist
- You need a different domain or tool outside this scope
## Instructions
- Clarify goals, constraints, and required inputs.
- Apply relevant best practices and validate outcomes.
- Provide actionable steps and verification.
You are a data scientist specializing in advanced analytics, machine learning, statistical modeling, and data-driven business insights.
## Purpose
Expert data scientist combining strong statistical foundations with modern machine learning techniques and business acumen. Masters the complete data science workflow from exploratory data analysis to production model deployment, with deep expertise in statistical methods, ML algorithms, and data visualization for actionable business insights.
## Capabilities
### Statistical Analysis & Methodology
- Descriptive statistics, inferential statistics, and hypothesis testing
description: Структурированное интервью-discovery ПЕРЕД проектированием. Два режима. FEATURE — заказчик описывает проблему, боль или цель без готового решения («менеджеры жалуются на…», «сделки теряются», «хочу чтобы…»): JTBD-интервью вскрывает проблему до решения и отдаёт discovery-brief в brainstorming. SYSTEM — запрос ориентации по проекту («сориентируй», «где мы сейчас», «что в тулчейне / на карте», «catch-up по…»): синтез по мета-слою (карта, CLAUDE.md, MEMORY, Открытые_вопросы, Tooling, git log). SKIP — чёткий директив на реализацию («интегрируй X», «закрой находку Y», «поправь Z»): это не discovery. SKIP — анализ бизнес-процесса из кода или диагностика просадки измеримой метрики/конверсии («как устроен процесс X», «process discovery», «где узкое место», «почему просела конверсия»): это skill process-analysis. Используй при «discovery interview», «проведи discovery», «сориентируй по проекту» и при расплывчатом проблемном запросе, даже если слово «discovery» не названо.
---
# Discovery Interview
Структурированное интервью, которое вскрывает **проблему** прежде, чем кто-либо
начнёт проектировать решение. Два режима — FEATURE (интервью заказчика перед
фичей) и SYSTEM (интервью-ориентация по состоянию проекта).
Зачем скил существует: запрос вида «менеджеры жалуются на X» или «хочу, чтобы Y» —
это симптом, не задача. Уйдёшь сразу в дизайн — спроектируешь решение не той
проблемы. Discovery interview удерживает разговор в проблемном поле ровно столько,
сколько нужно, чтобы понять *настоящую* потребность, и только потом передаёт
эстафету проектированию.
## Когда какой режим
| Запрос | Действие |
|---|---|
| Заказчик описал проблему / боль / цель без решения | режим **FEATURE** |
| Заказчик просит сориентировать по проекту | режим **SYSTEM** |
| Заказчик дал чёткий директив («сделай X», «интегрируй Y») | скил не нужен — работай напрямую |
| Вопрос про устройство бизнес-процесса из кода | скил `process-analysis`, не этот |
## Несущий принцип — три слоя-источника
Этот скил соседствует со скилом `process-analysis` (раздел C10 карты). Чтобы не
дублировать его, способности разведены по **слою данных**, с которым работают:
"note":"Триггер-eval: should_trigger=true → должен вызваться discovery-interview; false → должен сработать другой инструмент (expected_skill). Особое внимание — near-miss к process-analysis (C10).",
"evals":[
{"id":1,"should_trigger":true,"expected_skill":"discovery-interview/FEATURE","prompt":"менеджеры жалуются что не видят, какие сделки сегодня надо обзвонить — каждое утро роются в фильтрах вручную"},
{"id":2,"should_trigger":false,"expected_skill":"process-analysis","prompt":"у меня ощущение что лиды из B2 проседают по конверсии, но не пойму почему — хочу разобраться"},
{"id":3,"should_trigger":true,"expected_skill":"discovery-interview/FEATURE","prompt":"хочу чтобы поставщики сами видели свой баланс, а то постоянно пишут в поддержку спрашивают"},
{"id":4,"should_trigger":true,"expected_skill":"discovery-interview/FEATURE","prompt":"проведи discovery interview по идее напоминаний — я пока сам не уверен что именно нужно"},
{"id":5,"should_trigger":true,"expected_skill":"discovery-interview/FEATURE","prompt":"не нравится как сейчас сделана выгрузка отчётов, неудобно, давай покопаем что не так"},
{"id":6,"should_trigger":true,"expected_skill":"discovery-interview/FEATURE","prompt":"клиенты часто отваливаются на этапе оплаты, надо понять что там за проблема"},
{"id":7,"should_trigger":true,"expected_skill":"discovery-interview/SYSTEM","prompt":"сориентируй меня — где мы сейчас по проекту, что закрыто что нет"},
{"id":8,"should_trigger":true,"expected_skill":"discovery-interview/SYSTEM","prompt":"что у нас вообще в тулчейне по безопасности, я запутался"},
{"id":9,"should_trigger":true,"expected_skill":"discovery-interview/SYSTEM","prompt":"вернулся после недели отсутствия, сделай catch-up что произошло по проекту"},
{"id":10,"should_trigger":true,"expected_skill":"discovery-interview/SYSTEM","prompt":"что там на карте в разделе биллинга, какие узлы"},
{"id":11,"should_trigger":false,"expected_skill":"process-analysis","prompt":"как устроен процесс обработки сделки от создания до закрытия — пройди по коду"},
{"id":12,"should_trigger":false,"expected_skill":"process-analysis","prompt":"где узкое место в воронке лидов, какой шаг тормозит"},
{"id":13,"should_trigger":false,"expected_skill":"process-analysis","prompt":"сделай process discovery по джобам импорта лидов"},
{"id":14,"should_trigger":false,"expected_skill":"process-analysis","prompt":"посчитай метрики процесса: cycle time по статусам сделок"},
{"id":15,"should_trigger":false,"expected_skill":"directive (no skill)","prompt":"интегрируй openapi-mcp-server в .mcp.json"},
{"id":16,"should_trigger":false,"expected_skill":"directive (no skill)","prompt":"закрой находку аудита G7 по AdminBillingController"},
{"id":17,"should_trigger":false,"expected_skill":"systematic-debugging","prompt":"поправь падающий тест RlsSmokeTest, он валится на teardown"},
{"id":18,"should_trigger":false,"expected_skill":"directive (no skill)","prompt":"добавь endpoint POST /api/deals/{id}/archive"},
{"id":19,"should_trigger":false,"expected_skill":"write-spec / brainstorming","prompt":"напиши спеку для фичи мультивалютного биллинга"},
{"id":20,"should_trigger":false,"expected_skill":"audit-portal","prompt":"проведи полный аудит портала перед релизом"}
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
description: Generate Mermaid diagrams from user requirements. Supports flowcharts, sequence diagrams, class diagrams, ER diagrams, Gantt charts, and 18 more diagram types.
allowed-tools: Read Write Edit
metadata:
argument-hint: "[diagram description or requirements]"
---
# Mermaid Diagram Generator
Generate high-quality Mermaid diagram code based on user requirements.
## Workflow
1. **Understand Requirements**: Analyze user description to determine the most suitable diagram type
2. **Read Documentation**: Read the corresponding syntax reference for the diagram type
3. **Generate Code**: Generate Mermaid code following the specification
4. **Apply Styling**: Apply appropriate themes and style configurations
## Diagram Type Reference
Select the appropriate diagram type and read the corresponding documentation:
> ## Please edit the corresponding file in [/packages/mermaid/src/docs/syntax/architecture.md](../../packages/mermaid/src/docs/syntax/architecture.md).
# Architecture Diagrams Documentation (v11.1.0+)
> In the context of mermaid-js, the architecture diagram is used to show the relationship between services and resources commonly found within the Cloud or CI/CD deployments. In an architecture diagram, services (nodes) are connected by edges. Related services can be placed within groups to better illustrate how they are organized.
## Example
```mermaid-example
architecture-beta
group api(cloud)[API]
service db(database)[Database] in api
service disk1(disk)[Storage] in api
service disk2(disk)[Storage] in api
service server(server)[Server] in api
db:L -- R:server
disk1:T -- B:server
disk2:T -- B:db
```
```mermaid
architecture-beta
group api(cloud)[API]
service db(database)[Database] in api
service disk1(disk)[Storage] in api
service disk2(disk)[Storage] in api
service server(server)[Server] in api
db:L -- R:server
disk1:T -- B:server
disk2:T -- B:db
```
## Syntax
The building blocks of an architecture are `groups`, `services`, `edges`, and `junctions`.
For supporting components, icons are declared by surrounding the icon name with `()`, while labels are declared by surrounding the text with `[]`.
To begin an architecture diagram, use the keyword `architecture-beta`, followed by your groups, services, edges, and junctions. While each of the 3 building blocks can be declared in any order, care must be taken to ensure the identifier was previously declared by another component.
### Groups
The syntax for declaring a group is:
```
group {group id}({icon name})[{title}] (in {parent id})?
```
Put together:
```
group public_api(cloud)[Public API]
```
creates a group identified as `public_api`, uses the icon `cloud`, and has the label `Public API`.
Additionally, groups can be placed within a group using the optional `in` keyword
```
group private_api(cloud)[Private API] in public_api
```
### Services
The syntax for declaring a service is:
```
service {service id}({icon name})[{title}] (in {parent id})?
```
Put together:
```
service database1(database)[My Database]
```
creates the service identified as `database1`, using the icon `database`, with the label `My Database`.
If the service belongs to a group, it can be placed inside it through the optional `in` keyword
```
service database1(database)[My Database] in private_api
The side of the service the edge comes out of is specified by adding a colon (`:`) to the side of the service connecting to the arrow and adding `L|R|T|B`
For example:
```
db:R -- L:server
```
creates an edge between the services `db` and `server`, with the edge coming out of the right of `db` and the left of `server`.
```
db:T -- L:server
```
creates a 90 degree edge between the services `db` and `server`, with the edge coming out of the top of `db` and the left of `server`.
#### Arrows
Arrows can be added to each side of an edge by adding `<` before the direction on the left, and/or `>` after the direction on the right.
For example:
```
subnet:R --> L:gateway
```
creates an edge with the arrow going into the `gateway` service
#### Edges out of Groups
To have an edge go from a group to another group or service within another group, the `{group}` modifier can be added after the `serviceId`.
For example:
```
service server[Server] in groupOne
service subnet[Subnet] in groupTwo
server{group}:B --> T:subnet{group}
```
creates an edge going out of `groupOne`, adjacent to `server`, and into `groupTwo`, adjacent to `subnet`.
It's important to note that `groupId`s cannot be used for specifying edges and the `{group}` modifier can only be used for services within a group.
### Junctions
Junctions are a special type of node which acts as a potential 4-way split between edges.
The syntax for declaring a junction is:
```
junction {junction id} (in {parent id})?
```
```mermaid-example
architecture-beta
service left_disk(disk)[Disk]
service top_disk(disk)[Disk]
service bottom_disk(disk)[Disk]
service top_gateway(internet)[Gateway]
service bottom_gateway(internet)[Gateway]
junction junctionCenter
junction junctionRight
left_disk:R -- L:junctionCenter
top_disk:B -- T:junctionCenter
bottom_disk:T -- B:junctionCenter
junctionCenter:R -- L:junctionRight
top_gateway:B -- T:junctionRight
bottom_gateway:T -- B:junctionRight
```
```mermaid
architecture-beta
service left_disk(disk)[Disk]
service top_disk(disk)[Disk]
service bottom_disk(disk)[Disk]
service top_gateway(internet)[Gateway]
service bottom_gateway(internet)[Gateway]
junction junctionCenter
junction junctionRight
left_disk:R -- L:junctionCenter
top_disk:B -- T:junctionCenter
bottom_disk:T -- B:junctionCenter
junctionCenter:R -- L:junctionRight
top_gateway:B -- T:junctionRight
bottom_gateway:T -- B:junctionRight
```
## Icons
By default, architecture diagram supports the following icons: `cloud`, `database`, `disk`, `internet`, `server`.
Users can use any of the 200,000+ icons available in iconify.design, or add other custom icons, by [registering an icon pack](../config/icons.md).
After the icons are installed, they can be used in the architecture diagram by using the format "name:icon-name", where name is the value used when registering the icon pack.
> ## Please edit the corresponding file in [/packages/mermaid/src/docs/syntax/block.md](../../packages/mermaid/src/docs/syntax/block.md).
# Block Diagrams Documentation
## Introduction to Block Diagrams
```mermaid-example
block
columns 1
db(("DB"))
blockArrowId6<[" "]>(down)
block:ID
A
B["A wide one in the middle"]
C
end
space
D
ID --> D
C --> D
style B fill:#969,stroke:#333,stroke-width:4px
```
```mermaid
block
columns 1
db(("DB"))
blockArrowId6<[" "]>(down)
block:ID
A
B["A wide one in the middle"]
C
end
space
D
ID --> D
C --> D
style B fill:#969,stroke:#333,stroke-width:4px
```
### Definition and Purpose
Block diagrams are an intuitive and efficient way to represent complex systems, processes, or architectures visually. They are composed of blocks and connectors, where blocks represent the fundamental components or functions, and connectors show the relationship or flow between these components. This method of diagramming is essential in various fields such as engineering, software development, and process management.
The primary purpose of block diagrams is to provide a high-level view of a system, allowing for easy understanding and analysis without delving into the intricate details of each component. This makes them particularly useful for simplifying complex systems and for explaining the overall structure and interaction of components within a system.
Many people use mermaid flowcharts for this purpose. A side-effect of this is that the automatic layout sometimes move shapes to positions that the diagram maker does not want. Block diagrams use a different approach. In this diagram we give the author full control over where the shapes are positioned.
### General Use Cases
Block diagrams have a wide range of applications across various industries and disciplines. Some of the key use cases include:
- **Software Architecture**: In software development, block diagrams can be used to illustrate the architecture of a software application. This includes showing how different modules or services interact, data flow, and high-level component interaction.
- **Network Diagrams**: Block diagrams are ideal for representing network architectures in IT and telecommunications. They can depict how different network devices and services are interconnected, including routers, switches, firewalls, and the flow of data across the network.
- **Process Flowcharts**: In business and manufacturing, block diagrams can be employed to create process flowcharts. These flowcharts represent various stages of a business or manufacturing process, helping to visualize the sequence of steps, decision points, and the flow of control.
- **Electrical Systems**: Engineers use block diagrams to represent electrical systems and circuitry. They can illustrate the high-level structure of an electrical system, the interaction between different electrical components, and the flow of electrical currents.
- **Educational Purposes**: Block diagrams are also extensively used in educational materials to explain complex concepts and systems in a simplified manner. They help in breaking down and visualizing scientific theories, engineering principles, and technological systems.
These examples demonstrate the versatility of block diagrams in providing clear and concise representations of complex systems. Their simplicity and clarity make them a valuable tool for professionals across various fields to communicate complex ideas effectively.
In the following sections, we will delve into the specifics of creating and manipulating block diagrams using Mermaid, covering everything from basic syntax to advanced configurations and styling.
Creating block diagrams with Mermaid is straightforward and accessible. This section introduces the basic syntax and structure needed to start building simple diagrams. Understanding these foundational concepts is key to efficiently utilizing Mermaid for more complex diagramming tasks.
### Simple Block Diagrams
#### Basic Structure
At its core, a block diagram consists of blocks representing different entities or components. In Mermaid, these blocks are easily created using simple text labels. The most basic form of a block diagram can be a series of blocks without any connectors.
**Example - Simple Block Diagram**:
To create a simple block diagram with three blocks labeled 'a', 'b', and 'c', the syntax is as follows:
```mermaid-example
block
a b c
```
```mermaid
block
a b c
```
This example will produce a horizontal sequence of three blocks. Each block is automatically spaced and aligned for optimal readability.
### Defining the number of columns to use
#### Column Usage
While simple block diagrams are linear and straightforward, more complex systems may require a structured layout. Mermaid allows for the organization of blocks into multiple columns, facilitating the creation of more intricate and detailed diagrams.
**Example - Multi-Column Diagram:**
In scenarios where you need to distribute blocks across multiple columns, you can specify the number of columns and arrange the blocks accordingly. Here's how to create a block diagram with three columns and four blocks, where the fourth block appears in a second row:
```mermaid-example
block
columns 3
a b c d
```
```mermaid
block
columns 3
a b c d
```
This syntax instructs Mermaid to arrange the blocks 'a', 'b', 'c', and 'd' across three columns, wrapping to the next row as needed. This feature is particularly useful for representing layered or multi-tiered systems, such as network layers or hierarchical structures.
These basic building blocks of Mermaid's block diagrams provide a foundation for more complex diagramming. The simplicity of the syntax allows for quick creation and iteration of diagrams, making it an efficient tool for visualizing ideas and concepts. In the next section, we'll explore advanced block configuration options, including setting block widths and creating composite blocks.
## 3. Advanced Block Configuration
Building upon the basics, this section delves into more advanced features of block diagramming in Mermaid. These features allow for greater flexibility and complexity in diagram design, accommodating a wider range of use cases and scenarios.
### Setting Block Width
#### Spanning Multiple Columns
In more complex diagrams, you may need blocks that span multiple columns to emphasize certain components or to represent larger entities. Mermaid allows for the adjustment of block widths to cover multiple columns, enhancing the diagram's readability and structure.
**Example - Block Spanning Multiple Columns**:
To create a block diagram where one block spans across two columns, you can specify the desired width for each block:
```mermaid-example
block
columns 3
a["A label"] b:2 c:2 d
```
```mermaid
block
columns 3
a["A label"] b:2 c:2 d
```
In this example, the block labeled "A labels" spans one column, while blocks 'b', 'c' span 2 columns, and 'd' is again allocated its own column. This flexibility in block sizing is crucial for accurately representing systems with components of varying significance or size.
### Creating Composite Blocks
#### Nested Blocks
Composite blocks, or blocks within blocks, are an advanced feature in Mermaid's block diagram syntax. They allow for the representation of nested or hierarchical systems, where one component encompasses several subcomponents.
**Example - Composite Blocks:**
Creating a composite block involves defining a parent block and then nesting other blocks within it. Here's how to define a composite block with nested elements:
```mermaid-example
block
block
D
end
A["A: I am a wide one"]
```
```mermaid
block
block
D
end
A["A: I am a wide one"]
```
In this syntax, 'D' is a nested block within a larger parent block. This feature is particularly useful for depicting complex structures, such as a server with multiple services or a department within a larger organizational framework.
### Column Width Dynamics
#### Adjusting Widths
Mermaid also allows for dynamic adjustment of column widths based on the content of the blocks. The width of the columns is determined by the widest block in the column, ensuring that the diagram remains balanced and readable.
**Example - Dynamic Column Widths:**
In diagrams with varying block sizes, Mermaid automatically adjusts the column widths to fit the largest block in each column. Here's an example:
```mermaid-example
block
columns 3
a:3
block:group1:2
columns 2
h i j k
end
g
block:group2:3
%% columns auto (default)
l m n o p q r
end
```
```mermaid
block
columns 3
a:3
block:group1:2
columns 2
h i j k
end
g
block:group2:3
%% columns auto (default)
l m n o p q r
end
```
This example demonstrates how Mermaid dynamically adjusts the width of the columns to accommodate the widest block, in this case, 'a' and the composite block 'e'. This dynamic adjustment is essential for creating visually balanced and easy-to-understand diagrams.
**Merging Blocks Horizontally:**
In scenarios where you need to stack blocks horizontally, you can use column width to accomplish the task. Blocks can be arranged vertically by putting them in a single column. Here is how you can create a block diagram in which 4 blocks are stacked on top of each other:
```mermaid-example
block
block
columns 1
a["A label"] b c d
end
```
```mermaid
block
block
columns 1
a["A label"] b c d
end
```
In this example, the width of the merged block dynamically adjusts to the width of the largest child block.
With these advanced configuration options, Mermaid's block diagrams can be tailored to represent a wide array of complex systems and structures. The flexibility offered by these features enables users to create diagrams that are both informative and visually appealing. In the following sections, we will explore further capabilities, including different block shapes and linking options.
## 4. Block Varieties and Shapes
Mermaid's block diagrams are not limited to standard rectangular shapes. A variety of block shapes are available, allowing for a more nuanced and tailored representation of different types of information or entities. This section outlines the different block shapes you can use in Mermaid and their specific applications.
### Standard and Special Block Shapes
Mermaid supports a range of block shapes to suit different diagramming needs, from basic geometric shapes to more specialized forms.
#### Example - Round Edged Block
To create a block with round edges, which can be used to represent a softer or more flexible component:
```mermaid-example
block
id1("This is the text in the box")
```
```mermaid
block
id1("This is the text in the box")
```
#### Example - Stadium-Shaped Block
A stadium-shaped block, resembling an elongated circle, can be used for components that are process-oriented:
```mermaid-example
block
id1(["This is the text in the box"])
```
```mermaid
block
id1(["This is the text in the box"])
```
#### Example - Subroutine Shape
For representing subroutines or contained processes, a block with double vertical lines is useful:
```mermaid-example
block
id1[["This is the text in the box"]]
```
```mermaid
block
id1[["This is the text in the box"]]
```
#### Example - Cylindrical Shape
The cylindrical shape is ideal for representing databases or storage components:
```mermaid-example
block
id1[("Database")]
```
```mermaid
block
id1[("Database")]
```
#### Example - Circle Shape
A circle can be used for centralized or pivotal components:
```mermaid-example
block
id1(("This is the text in the circle"))
```
```mermaid
block
id1(("This is the text in the circle"))
```
#### Example - Asymmetric, Rhombus, and Hexagon Shapes
For decision points, use a rhombus, and for unique or specialized processes, asymmetric and hexagon shapes can be utilized:
**Asymmetric**
```mermaid-example
block
id1>"This is the text in the box"]
```
```mermaid
block
id1>"This is the text in the box"]
```
**Rhombus**
```mermaid-example
block
id1{"This is the text in the box"}
```
```mermaid
block
id1{"This is the text in the box"}
```
**Hexagon**
```mermaid-example
block
id1{{"This is the text in the box"}}
```
```mermaid
block
id1{{"This is the text in the box"}}
```
#### Example - Parallelogram and Trapezoid Shapes
Parallelogram and trapezoid shapes are perfect for inputs/outputs and transitional processes:
```mermaid-example
block
id1[/"This is the text in the box"/]
id2[\"This is the text in the box"\]
A[/"Christmas"\]
B[\"Go shopping"/]
```
```mermaid
block
id1[/"This is the text in the box"/]
id2[\"This is the text in the box"\]
A[/"Christmas"\]
B[\"Go shopping"/]
```
#### Example - Double Circle
For highlighting critical or high-priority components, a double circle can be effective:
```mermaid-example
block
id1((("This is the text in the circle")))
```
```mermaid
block
id1((("This is the text in the circle")))
```
### Block Arrows and Space Blocks
Mermaid also offers unique shapes like block arrows and space blocks for directional flow and spacing.
#### Example - Block Arrows
Block arrows can visually indicate direction or flow within a process:
```mermaid-example
block
blockArrowId<["Label"]>(right)
blockArrowId2<["Label"]>(left)
blockArrowId3<["Label"]>(up)
blockArrowId4<["Label"]>(down)
blockArrowId5<["Label"]>(x)
blockArrowId6<["Label"]>(y)
blockArrowId7<["Label"]>(x, down)
```
```mermaid
block
blockArrowId<["Label"]>(right)
blockArrowId2<["Label"]>(left)
blockArrowId3<["Label"]>(up)
blockArrowId4<["Label"]>(down)
blockArrowId5<["Label"]>(x)
blockArrowId6<["Label"]>(y)
blockArrowId7<["Label"]>(x, down)
```
#### Example - Space Blocks
Space blocks can be used to create intentional empty spaces in the diagram, which is useful for layout and readability:
```mermaid-example
block
columns 3
a space b
c d e
```
```mermaid
block
columns 3
a space b
c d e
```
or
```mermaid-example
block
ida space:3 idb idc
```
```mermaid
block
ida space:3 idb idc
```
Note that you can set how many columns the space block occupied using the number notation `space:num` where num is a number indicating the num columns width. You can also use `space` which defaults to one column.
The variety of shapes and special blocks in Mermaid enhances the expressive power of block diagrams, allowing for more accurate and context-specific representations. These options give users the flexibility to create diagrams that are both informative and visually appealing. In the next sections, we will explore the ways to connect these blocks and customize their appearance.
### Standard and Special Block Shapes
Discuss the various shapes available for blocks, including standard shapes and special forms like block arrows and space blocks.
## 5. Connecting Blocks with Edges
One of the key features of block diagrams in Mermaid is the ability to connect blocks using various types of edges or links. This section explores the different ways blocks can be interconnected to represent relationships and flows between components.
### Basic Linking and Arrow Types
The most fundamental aspect of connecting blocks is the use of arrows or links. These connectors depict the relationships or the flow of information between the blocks. Mermaid offers a range of arrow types to suit different diagramming needs.
**Example - Basic Links**
A simple link with an arrow can be created to show direction or flow from one block to another:
```mermaid-example
block
A space B
A-->B
```
```mermaid
block
A space B
A-->B
```
This example illustrates a direct connection from block 'A' to block 'B', using a straightforward arrow.
This syntax creates a line connecting 'A' and 'B', implying a relationship or connection without indicating a specific direction.
### Text on Links
In addition to connecting blocks, it's often necessary to describe or label the relationship. Mermaid allows for the inclusion of text on links, providing context to the connections.
Example - Text with Links
To add text to a link, the syntax includes the text within the link definition:
```mermaid-example
block
A space:2 B
A-- "X" -->B
```
```mermaid
block
A space:2 B
A-- "X" -->B
```
This example show how to add descriptive text to the links, enhancing the information conveyed by the diagram.
Example - Edges and Styles:
```mermaid-example
block
columns 1
db(("DB"))
blockArrowId6<[" "]>(down)
block:ID
A
B["A wide one in the middle"]
C
end
space
D
ID --> D
C --> D
style B fill:#939,stroke:#333,stroke-width:4px
```
```mermaid
block
columns 1
db(("DB"))
blockArrowId6<[" "]>(down)
block:ID
A
B["A wide one in the middle"]
C
end
space
D
ID --> D
C --> D
style B fill:#939,stroke:#333,stroke-width:4px
```
## 6. Styling and Customization
Beyond the structure and layout of block diagrams, Mermaid offers extensive styling options. These customization features allow for the creation of more visually distinctive and informative diagrams. This section covers how to apply individual styles to blocks and how to use classes for consistent styling across multiple elements.
### Individual Block Styling
Mermaid enables detailed styling of individual blocks, allowing you to apply various CSS properties such as color, stroke, and border thickness. This feature is especially useful for highlighting specific parts of a diagram or for adhering to certain visual themes.
#### Example - Styling a Single Block
To apply custom styles to a block, you can use the `style` keyword followed by the block identifier and the desired CSS properties:
Mermaid enables applying styling to classes, which could make styling easier if you want to apply a certain set of styles to multiple elements, as you could just link those elements to a class.
#### Example - Styling a Single Class
```mermaid-example
block
A space B
A-->B
classDef blue fill:#6e6ce6,stroke:#333,stroke-width:4px;
class A blue
style B fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5 5
```
```mermaid
block
A space B
A-->B
classDef blue fill:#6e6ce6,stroke:#333,stroke-width:4px;
class A blue
style B fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5 5
```
In this example, a class named 'blue' is defined and applied to block 'A', while block 'B' receives individual styling. This demonstrates the flexibility of Mermaid in applying both shared and unique styles within the same diagram.
The ability to style blocks individually or through classes provides a powerful tool for enhancing the visual impact and clarity of block diagrams. Whether emphasizing certain elements or maintaining a cohesive design across the diagram, these styling capabilities are central to effective diagramming. The next sections will present practical examples and use cases, followed by tips for troubleshooting common issues.
### 7. Practical Examples and Use Cases
The versatility of Mermaid's block diagrams becomes evident when applied to real-world scenarios. This section provides practical examples demonstrating the application of various features discussed in previous sections. These examples showcase how block diagrams can be used to represent complex systems and processes in an accessible and informative manner.
### Detailed Examples Illustrating Various Features
Combining the elements of structure, linking, and styling, we can create comprehensive diagrams that serve specific purposes in different contexts.
#### Example - System Architecture
Illustrating a simple software system architecture with interconnected components:
```mermaid-example
block
columns 3
Frontend blockArrowId6<[" "]>(right) Backend
space:2 down<[" "]>(down)
Disk left<[" "]>(left) Database[("Database")]
classDef front fill:#696,stroke:#333;
classDef back fill:#969,stroke:#333;
class Frontend front
class Backend,Database back
```
```mermaid
block
columns 3
Frontend blockArrowId6<[" "]>(right) Backend
space:2 down<[" "]>(down)
Disk left<[" "]>(left) Database[("Database")]
classDef front fill:#696,stroke:#333;
classDef back fill:#969,stroke:#333;
class Frontend front
class Backend,Database back
```
This example shows a basic architecture with a frontend, backend, and database. The blocks are styled to differentiate between types of components.
#### Example - Business Process Flow
Representing a business process flow with decision points and multiple stages:
These practical examples and scenarios underscore the utility of Mermaid block diagrams in simplifying and effectively communicating complex information across various domains.
The next section, 'Troubleshooting and Common Issues', will provide insights into resolving common challenges encountered when working with Mermaid block diagrams, ensuring a smooth diagramming experience.
## 8. Troubleshooting and Common Issues
Working with Mermaid block diagrams can sometimes present challenges, especially as the complexity of the diagrams increases. This section aims to provide guidance on resolving common issues and offers tips for managing more intricate diagram structures.
### Common Syntax Errors
Understanding and avoiding common syntax errors is key to a smooth experience with Mermaid diagrams.
#### Example - Incorrect Linking
A common mistake is incorrect linking syntax, which can lead to unexpected results or broken diagrams:
```
block
A - B
```
**Correction**:
Ensure that links between blocks are correctly specified with arrows (--> or ---) to define the direction and type of connection. Also remember that one of the fundamentals for block diagram is to give the author full control of where the boxes are positioned so in the example you need to add a space between the boxes:
```mermaid-example
block
A space B
A --> B
```
```mermaid
block
A space B
A --> B
```
#### Example - Misplaced Styling
Applying styles in the wrong context or with incorrect syntax can lead to blocks not being styled as intended:
```mermaid-example
block
A
style A fill#969;
```
```mermaid
block
A
style A fill#969;
```
**Correction:**
Correct the syntax by ensuring proper separation of style properties with commas and using the correct CSS property format:
```mermaid-example
block
A
style A fill:#969,stroke:#333;
```
```mermaid
block
A
style A fill:#969,stroke:#333;
```
### Tips for Complex Diagram Structures
Managing complexity in Mermaid diagrams involves planning and employing best practices.
#### Modular Design
Break down complex diagrams into smaller, more manageable components. This approach not only makes the diagram easier to understand but also simplifies the creation and maintenance process.
#### Consistent Styling
Use classes to maintain consistent styling across similar elements. This not only saves time but also ensures a cohesive and professional appearance.
#### Comments and Documentation
Use comments with `%%` within the Mermaid syntax to document the purpose of various parts of the diagram. This practice is invaluable for maintaining clarity, especially when working in teams or returning to a diagram after some time.
With these troubleshooting tips and best practices, you can effectively manage and resolve common issues in Mermaid block diagrams. The final section, 'Conclusion', will summarize the key points covered in this documentation and invite user feedback for continuous improvement.
> ## Please edit the corresponding file in [/packages/mermaid/src/docs/syntax/c4.md](../../packages/mermaid/src/docs/syntax/c4.md).
# C4 Diagrams
> C4 Diagram: This is an experimental diagram for now. The syntax and properties can change in future releases. Proper documentation will be provided when the syntax is stable.
Mermaid's C4 diagram syntax is compatible with plantUML. See example below:
```mermaid-example
C4Context
title System Context diagram for Internet Banking System
Enterprise_Boundary(b0, "BankBoundary0") {
Person(customerA, "Banking Customer A", "A customer of the bank, with personal bank accounts.")
For an example, see the source code demos/index.html
5 types of C4 charts are supported.
- System Context (C4Context)
- Container diagram (C4Container)
- Component diagram (C4Component)
- Dynamic diagram (C4Dynamic)
- Deployment diagram (C4Deployment)
Please refer to the linked document [C4-PlantUML syntax](https://github.com/plantuml-stdlib/C4-PlantUML/blob/master/README.md) for how to write the C4 diagram.
C4 diagram is fixed style, such as css color, so different css is not provided under different skins.
updateElementStyle and UpdateElementStyle are written in the diagram last part. updateElementStyle is inconsistent with the original definition and updates the style of the relationship, including the offset of the text label relative to the original position.
The layout does not use a fully automated layout algorithm. The position of shapes is adjusted by changing the order in which statements are written. So there is no plan to support the following Layout statements.
The number of shapes per row and the number of boundaries can be adjusted using UpdateLayoutConfig.
- Layout
- Lay_U, Lay_Up
- Lay_D, Lay_Down
- Lay_L, Lay_Left
- Lay_R, Lay_Right
The following unfinished features are not supported in the short term.
- [x] Rel(from, to, label, ?techn, ?descr, ?sprite, ?tags, $link)
- [x] BiRel (bidirectional relationship)
- [x] Rel_U, Rel_Up
- [x] Rel_D, Rel_Down
- [x] Rel_L, Rel_Left
- [x] Rel_R, Rel_Right
- [x] Rel_Back
- [x] RelIndex \* Compatible with C4-PlantUML syntax, but ignores the index parameter. The sequence number is determined by the order in which the rel statements are written.
- [ ] Custom tags/stereotypes support and skin param updates
- [ ] AddElementTag(tagStereo, ?bgColor, ?fontColor, ?borderColor, ?shadowing, ?shape, ?sprite, ?techn, ?legendText, ?legendSprite): Introduces a new element tag. The styles of the tagged elements are updated and the tag is displayed in the calculated legend.
- [ ] AddRelTag(tagStereo, ?textColor, ?lineColor, ?lineStyle, ?sprite, ?techn, ?legendText, ?legendSprite): Introduces a new Relationship tag. The styles of the tagged relationships are updated and the tag is displayed in the calculated legend.
- [x] UpdateElementStyle(elementName, ?bgColor, ?fontColor, ?borderColor, ?shadowing, ?shape, ?sprite, ?techn, ?legendText, ?legendSprite): This call updates the default style of the elements (component, ...) and creates no additional legend entry.
- [x] UpdateRelStyle(from, to, ?textColor, ?lineColor, ?offsetX, ?offsetY): This call updates the default relationship colors and creates no additional legend entry. Two new parameters, offsetX and offsetY, are added to set the offset of the original position of the text.
- [ ] RoundedBoxShape(): This call returns the name of the rounded box shape and can be used as ?shape argument.
- [ ] EightSidedShape(): This call returns the name of the eight sided shape and can be used as ?shape argument.
- [ ] DashedLine(): This call returns the name of the dashed line and can be used as ?lineStyle argument.
- [ ] DottedLine(): This call returns the name of the dotted line and can be used as ?lineStyle argument.
- [ ] BoldLine(): This call returns the name of the bold line and can be used as ?lineStyle argument.
- [x] UpdateLayoutConfig(?c4ShapeInRow, ?c4BoundaryInRow): New. This call updates the default c4ShapeInRow(4) and c4BoundaryInRow(2).
There are two ways to assign parameters with question marks. One uses the non-named parameter assignment method in the order of the parameters, and the other uses the named parameter assignment method, where the name must start with a $ symbol.
Example: UpdateRelStyle(from, to, ?textColor, ?lineColor, ?offsetX, ?offsetY)
title Container diagram for Internet Banking System
System_Ext(email_system, "E-Mail System", "The internal Microsoft Exchange system", $tags="v1.0")
Person(customer, Customer, "A customer of the bank, with personal bank accounts", $tags="v1.0")
Container_Boundary(c1, "Internet Banking") {
Container(spa, "Single-Page App", "JavaScript, Angular", "Provides all the Internet banking functionality to customers via their web browser")
Container_Ext(mobile_app, "Mobile App", "C#, Xamarin", "Provides a limited subset of the Internet banking functionality to customers via their mobile device")
Container(web_app, "Web Application", "Java, Spring MVC", "Delivers the static content and the Internet banking SPA")
title Container diagram for Internet Banking System
System_Ext(email_system, "E-Mail System", "The internal Microsoft Exchange system", $tags="v1.0")
Person(customer, Customer, "A customer of the bank, with personal bank accounts", $tags="v1.0")
Container_Boundary(c1, "Internet Banking") {
Container(spa, "Single-Page App", "JavaScript, Angular", "Provides all the Internet banking functionality to customers via their web browser")
Container_Ext(mobile_app, "Mobile App", "C#, Xamarin", "Provides a limited subset of the Internet banking functionality to customers via their mobile device")
Container(web_app, "Web Application", "Java, Spring MVC", "Delivers the static content and the Internet banking SPA")
title Component diagram for Internet Banking System - API Application
Container(spa, "Single Page Application", "javascript and angular", "Provides all the internet banking functionality to customers via their web browser.")
Container(ma, "Mobile App", "Xamarin", "Provides a limited subset to the internet banking functionality to customers via their mobile device.")
title Component diagram for Internet Banking System - API Application
Container(spa, "Single Page Application", "javascript and angular", "Provides all the internet banking functionality to customers via their web browser.")
Container(ma, "Mobile App", "Xamarin", "Provides a limited subset to the internet banking functionality to customers via their mobile device.")
Container(c1, "Single-Page Application", "JavaScript and Angular", "Provides all of the Internet banking functionality to customers via their web browser.")
Container_Boundary(b, "API Application") {
Component(c3, "Security Component", "Spring Bean", "Provides functionality Related to signing in, changing passwords, etc.")
Component(c2, "Sign In Controller", "Spring MVC Rest Controller", "Allows users to sign in to the Internet Banking System.")
Container(c1, "Single-Page Application", "JavaScript and Angular", "Provides all of the Internet banking functionality to customers via their web browser.")
Container_Boundary(b, "API Application") {
Component(c3, "Security Component", "Spring Bean", "Provides functionality Related to signing in, changing passwords, etc.")
Component(c2, "Sign In Controller", "Spring MVC Rest Controller", "Allows users to sign in to the Internet Banking System.")
title Deployment Diagram for Internet Banking System - Live
Deployment_Node(mob, "Customer's mobile device", "Apple IOS or Android"){
Container(mobile, "Mobile App", "Xamarin", "Provides a limited subset of the Internet Banking functionality to customers via their mobile device.")
}
Deployment_Node(comp, "Customer's computer", "Microsoft Windows or Apple macOS"){
Deployment_Node(browser, "Web Browser", "Google Chrome, Mozilla Firefox,<br/> Apple Safari or Microsoft Edge"){
Container(spa, "Single Page Application", "JavaScript and Angular", "Provides all of the Internet Banking functionality to customers via their web browser.")
}
}
Deployment_Node(plc, "Big Bank plc", "Big Bank plc data center"){
title Deployment Diagram for Internet Banking System - Live
Deployment_Node(mob, "Customer's mobile device", "Apple IOS or Android"){
Container(mobile, "Mobile App", "Xamarin", "Provides a limited subset of the Internet Banking functionality to customers via their mobile device.")
}
Deployment_Node(comp, "Customer's computer", "Microsoft Windows or Apple macOS"){
Deployment_Node(browser, "Web Browser", "Google Chrome, Mozilla Firefox,<br/> Apple Safari or Microsoft Edge"){
Container(spa, "Single Page Application", "JavaScript and Angular", "Provides all of the Internet Banking functionality to customers via their web browser.")
}
}
Deployment_Node(plc, "Big Bank plc", "Big Bank plc data center"){
> ## Please edit the corresponding file in [/packages/mermaid/src/docs/config/configuration.md](../../packages/mermaid/src/docs/config/configuration.md).
# Configuration
When mermaid starts, configuration is extracted to determine a configuration to be used for a diagram. There are 3 sources for configuration:
- The default configuration
- Overrides at the site level are set by the initialize call, and will be applied to all diagrams in the site/app. The term for this is the **siteConfig**.
- Frontmatter (v10.5.0+) - diagram authors can update selected configuration parameters in the frontmatter of the diagram. These are applied to the render config.
- Directives (Deprecated by Frontmatter) - diagram authors can update selected configuration parameters directly in the diagram code via directives. These are applied to the render config.
**The render config** is configuration that is used when rendering by applying these configurations.
## Frontmatter config
The entire mermaid configuration (except the secure configs) can be overridden by the diagram author in the frontmatter of the diagram. The frontmatter is a YAML block at the top of the diagram.
```mermaid-example
---
title: Hello Title
config:
theme: base
themeVariables:
primaryColor: "#00ff00"
---
flowchart
Hello --> World
```
```mermaid
---
title: Hello Title
config:
theme: base
themeVariables:
primaryColor: "#00ff00"
---
flowchart
Hello --> World
```
## Theme configuration
## Starting mermaid
```mermaid-example
sequenceDiagram
Site->>mermaid: initialize
Site->>mermaid: content loaded
mermaid->>mermaidAPI: init
```
```mermaid
sequenceDiagram
Site->>mermaid: initialize
Site->>mermaid: content loaded
mermaid->>mermaidAPI: init
```
## Initialize
The initialize call is applied **only once**. It is called by the site integrator in order to override the default configuration at a site level.
## configApi.reset
This method resets the configuration for a diagram to the overall site configuration, which is the configuration provided by the site integrator. Before each rendering of a diagram, reset is called at the very beginning.
> ## Please edit the corresponding file in [/packages/mermaid/src/docs/config/directives.md](../../packages/mermaid/src/docs/config/directives.md).
# Directives
> **Warning**
> Directives are deprecated from v10.5.0. Please use the `config` key in frontmatter to pass configuration. See [Configuration](./configuration.md) for more details.
## Directives
Directives give a diagram author the capability to alter the appearance of a diagram before rendering by changing the applied configuration.
The significance of having directives is that you have them available while writing the diagram, and can modify the default global and diagram-specific configurations. So, directives are applied on top of the default configuration. The beauty of directives is that you can use them to alter configuration settings for a specific diagram, i.e. at an individual level.
While directives allow you to change most of the default configuration settings, there are some that are not available, for security reasons. Also, you have the _option to define the set of configurations_ that you wish to allow diagram authors to override with directives.
## Types of Directives options
Mermaid basically supports two types of configuration options to be overridden by directives.
1. _General/Top Level configurations_ : These are the configurations that are available and applied to all the diagram. **Some of the most important top-level** configurations are:
- theme
- fontFamily
- logLevel
- securityLevel
- startOnLoad
- secure
2. _Diagram-specific configurations_ : These are the configurations that are available and applied to a specific diagram. For each diagram there are specific configuration that will alter how that particular diagram looks and behaves.
For example, `mirrorActors` is a configuration that is specific to the `SequenceDiagram` and alters whether the actors are mirrored or not. So this config is available only for the `SequenceDiagram` type.
**NOTE:** Not all configuration options are listed here. To get hold of all the configuration options, please refer to the [defaultConfig.ts](https://github.com/mermaid-js/mermaid/blob/develop/packages/mermaid/src/defaultConfig.ts) in the source code.
> **Note**
> We plan to publish a complete list of top-level configurations & diagram-specific configurations with their possible values in the docs soon.
## Declaring directives
Now that we have defined the types of configurations that are available, we can learn how to declare directives.
A directive always starts and ends with `%%` signs with directive text in between, like `%% {directive_text} %%`.
Here the structure of a directive text is like a nested key-value pair map or a JSON object with root being _init_. Where all the general configurations are defined in the top level, and all the diagram specific configurations are defined one level deeper with diagram type as key/root for that section.
The following code snippet shows the structure of a directive:
```
%%{
init: {
"theme": "dark",
"fontFamily": "monospace",
"logLevel": "info",
"htmlLabels": true,
"flowchart": {
"curve": "linear"
},
"sequence": {
"mirrorActors": true
}
}
}%%
```
You can also define the directives in a single line, like this:
Here the directive declaration will set the `logLevel` to `debug` and the `theme` to `dark` for a rendered mermaid diagram, changing the appearance of the diagram itself.
Note: You can use 'init' or 'initialize' as both are acceptable as init directives. Also note that `%%init%%` and `%%initialize%%` directives will be grouped together after they are parsed.
For example, parsing the above generates a single `%%init%%` JSON object below, combining the two directives and carrying over the last value given for `loglevel`:
```json
{
"logLevel": "fatal",
"theme": "dark",
"startOnLoad": true
}
```
This will then be sent to `mermaid.initialize(...)` for rendering.
## Directive Examples
Now that the concept of directives has been explained, let us see some more examples of directive usage:
### Changing theme via directive
The following code snippet changes `theme` to `forest`:
`%%{init: { "theme": "forest" } }%%`
Possible theme values are: `default`, `base`, `dark`, `forest` and `neutral`.
Default Value is `default`.
Example:
```mermaid-example
%%{init: { "theme": "forest" } }%%
graph TD
A(Forest) --> B[/Another/]
A --> C[End]
subgraph section
B
C
end
```
```mermaid
%%{init: { "theme": "forest" } }%%
graph TD
A(Forest) --> B[/Another/]
A --> C[End]
subgraph section
B
C
end
```
### Changing fontFamily via directive
The following code snippet changes fontFamily to Trebuchet MS, Verdana, Arial, Sans-Serif:
The following code snippet changes `logLevel` to `2`:
`%%{init: { "logLevel": 2 } }%%`
Possible `logLevel` values are:
- `1` for _debug_,
- `2` for _info_
- `3` for _warn_
- `4` for _error_
- `5` for _only fatal errors_
Default Value is `5`.
Example:
```mermaid-example
%%{init: { "logLevel": 2 } }%%
graph TD
A(Forest) --> B[/Another/]
A --> C[End]
subgraph section
B
C
end
```
```mermaid
%%{init: { "logLevel": 2 } }%%
graph TD
A(Forest) --> B[/Another/]
A --> C[End]
subgraph section
B
C
end
```
### Changing flowchart config via directive
Some common flowchart configurations are:
- ~~_htmlLabels_~~: Deprecated, [prefer setting this at the root level](/config/schema-docs/config#htmllabels).
- _curve_: linear/curve
- _diagramPadding_: number
- _useMaxWidth_: number
For a complete list of flowchart configurations, see [defaultConfig.ts](https://github.com/mermaid-js/mermaid/blob/develop/packages/mermaid/src/defaultConfig.ts) in the source code.
_Soon we plan to publish a complete list of all diagram-specific configurations updated in the docs._
The following code snippet changes flowchart config:
Here we are overriding only the flowchart config, and not the general config, setting `htmlLabels` to `true` and `curve` to `linear`.
> **Warning**
> **Deprecated:**`flowchart.htmlLabels` has been deprecated from (v\<MERMAID_RELEASE_VERSION>+). Use the global `htmlLabels` configuration instead. For example, instead of `"flowchart": { "htmlLabels": true }`, use `"htmlLabels": true` at the top level.
### Changing Sequence diagram config via directive
Some common sequence diagram configurations are:
- _width_: number
- _height_: number
- _messageAlign_: left, center, right
- _mirrorActors_: boolean
- _useMaxWidth_: boolean
- _rightAngles_: boolean
- _showSequenceNumbers_: boolean
- _wrap_: boolean
For a complete list of sequence diagram configurations, see [defaultConfig.ts](https://github.com/mermaid-js/mermaid/blob/develop/packages/mermaid/src/defaultConfig.ts) in the source code.
_Soon we plan to publish a complete list of all diagram-specific configurations updated in the docs._
So, `wrap` by default has a value of `false` for sequence diagrams.
Let us see an example:
```mermaid-example
sequenceDiagram
Alice->Bob: Hello Bob, how are you?
Bob->Alice: Fine, how did your mother like the book I suggested? And did you catch the new book about alien invasion?
Alice->Bob: Good.
Bob->Alice: Cool
```
```mermaid
sequenceDiagram
Alice->Bob: Hello Bob, how are you?
Bob->Alice: Fine, how did your mother like the book I suggested? And did you catch the new book about alien invasion?
Alice->Bob: Good.
Bob->Alice: Cool
```
Now let us enable wrap for sequence diagrams.
The following code snippet changes sequence diagram config for `wrap` to `true`:
`%%{init: { "sequence": { "wrap": true} } }%%`
By applying that snippet to the diagram above, `wrap` will be enabled:
A -->|"$$\overbrace{a+b+c}^{\text{note}}$$"| C("$$\pi r^2$$")
B --> D("$$x = \begin{cases} a &\text{if } b \\ c &\text{if } d \end{cases}$$")
C --> E("$$x(t)=c_1\begin{bmatrix}-\cos{t}+\sin{t}\\ 2\cos{t} \end{bmatrix}e^{2t}$$")
```
### Sequence
```mermaid-example
sequenceDiagram
autonumber
participant 1 as $$\alpha$$
participant 2 as $$\beta$$
1->>2: Solve: $$\sqrt{2+2}$$
2-->>1: Answer: $$2$$
Note right of 2: $$\sqrt{2+2}=\sqrt{4}=2$$
```
```mermaid
sequenceDiagram
autonumber
participant 1 as $$\alpha$$
participant 2 as $$\beta$$
1->>2: Solve: $$\sqrt{2+2}$$
2-->>1: Answer: $$2$$
Note right of 2: $$\sqrt{2+2}=\sqrt{4}=2$$
```
## Legacy Support
By default, MathML is used for rendering mathematical expressions. If you have users on [unsupported browsers](https://caniuse.com/?search=mathml), `legacyMathML` can be set in the config to fall back to CSS rendering. Note that **you must provide KaTeX's stylesheets on your own** as they do not come bundled with Mermaid.
Example with legacy mode enabled (the latest version of KaTeX's stylesheet can be found on their [docs](https://katex.org/docs/browser.html)):
```html
<!doctype html>
<!-- KaTeX requires the use of the HTML5 doctype. Without it, KaTeX may not render properly -->
<html lang="en">
<head>
<!-- Please ensure the stylesheet's version matches with the KaTeX version in your package-lock -->
Due to differences between default fonts across operating systems and browser's MathML implementations, inconsistent results can be seen across platforms. If having consistent results are important, or the most optimal rendered results are desired, `forceLegacyMathML` can be enabled in the config.
This option will always use KaTeX's stylesheet instead of only when MathML is not supported (as with `legacyMathML`). Note that only `forceLegacyMathML` needs to be set.
If including KaTeX's stylesheet is not a concern, enabling this option is recommended to avoid scenarios where no MathML implementation within a browser provides the desired output (as seen below).

> ## Please edit the corresponding file in [/packages/mermaid/src/docs/config/theming.md](../../packages/mermaid/src/docs/config/theming.md).
# Theme Configuration
Dynamic and integrated theme configuration was introduced in Mermaid version 8.7.0.
Themes can now be customized at the site-wide level, or on individual Mermaid diagrams. For site-wide theme customization, the `initialize` call is used. For diagram specific customization, frontmatter config is used.
## Available Themes
1. [**default**](https://github.com/mermaid-js/mermaid/blob/develop/packages/mermaid/src/themes/theme-default.js) - This is the default theme for all diagrams.
2. [**neutral**](https://github.com/mermaid-js/mermaid/blob/develop/packages/mermaid/src/themes/theme-neutral.js) - This theme is great for black and white documents that will be printed.
3. [**dark**](https://github.com/mermaid-js/mermaid/blob/develop/packages/mermaid/src/themes/theme-dark.js) - This theme goes well with dark-colored elements or dark-mode.
4. [**forest**](https://github.com/mermaid-js/mermaid/blob/develop/packages/mermaid/src/themes/theme-forest.js) - This theme contains shades of green.
5. [**base**](https://github.com/mermaid-js/mermaid/blob/develop/packages/mermaid/src/themes/theme-base.js) - This is the only theme that can be modified. Use this theme as the base for customizations.
## Site-wide Theme
To customize themes site-wide, call the `initialize` method on the `mermaid`.
Example of `initialize` call setting `theme` to `base`:
```javascript
mermaid.initialize({
securityLevel: 'loose',
theme: 'base',
});
```
## Diagram-specific Themes
To customize the theme of an individual diagram, use frontmatter config.
Example of frontmatter config setting the `theme` to `forest`:
```mermaid-example
---
config:
theme: 'forest'
---
graph TD
a --> b
```
```mermaid
---
config:
theme: 'forest'
---
graph TD
a --> b
```
> **Reminder**: the only theme that can be customized is the `base` theme. The following section covers how to use `themeVariables` for customizations.
## Customizing Themes with `themeVariables`
To make a custom theme, modify `themeVariables` via frontmatter config.
You will need to use the [base](#available-themes) theme as it is the only modifiable theme.
| themeVariables | Modifiable with frontmatter config | Object | `primaryColor`, `primaryTextColor`, `lineColor` ([see full list](#theme-variables)) |
Example of modifying `themeVariables` using frontmatter config:
```mermaid-example
---
config:
theme: 'base'
themeVariables:
primaryColor: '#BB2528'
primaryTextColor: '#fff'
primaryBorderColor: '#7C0000'
lineColor: '#F8B229'
secondaryColor: '#006100'
tertiaryColor: '#fff'
---
graph TD
A[Christmas] -->|Get money| B(Go shopping)
B --> C{Let me think}
B --> G[/Another/]
C ==>|One| D[Laptop]
C -->|Two| E[iPhone]
C -->|Three| F[fa:fa-car Car]
subgraph section
C
D
E
F
G
end
```
```mermaid
---
config:
theme: 'base'
themeVariables:
primaryColor: '#BB2528'
primaryTextColor: '#fff'
primaryBorderColor: '#7C0000'
lineColor: '#F8B229'
secondaryColor: '#006100'
tertiaryColor: '#fff'
---
graph TD
A[Christmas] -->|Get money| B(Go shopping)
B --> C{Let me think}
B --> G[/Another/]
C ==>|One| D[Laptop]
C -->|Two| E[iPhone]
C -->|Three| F[fa:fa-car Car]
subgraph section
C
D
E
F
G
end
```
## Color and Color Calculation
To ensure diagram readability, the default value of certain variables is calculated or derived from other variables. For example, `primaryBorderColor` is derived from the `primaryColor` variable. So if the `primaryColor` variable is customized, Mermaid will adjust `primaryBorderColor` automatically. Adjustments can mean a color inversion, a hue change, a darkening/lightening by 10%, etc.
The theming engine will only recognize hex colors and not color names. So, the value `#ff0000` will work, but `red` will not.
| darkMode | false | Affects how derived colors are calculated. Set value to `true` for dark mode. |
| background | #f4f4f4 | Used to calculate color for items that should either be background colored or contrasting to the background |
| fontFamily | trebuchet ms, verdana, arial | Font family for diagram text |
| fontSize | 16px | Font size in pixels |
| primaryColor | #fff4dd | Color to be used as background in nodes, other colors will be derived from this |
| primaryTextColor | calculated from darkMode #ddd/#333 | Color to be used as text color in nodes using `primaryColor` |
| secondaryColor | calculated from primaryColor | |
| primaryBorderColor | calculated from primaryColor | Color to be used as border in nodes using `primaryColor` |
| secondaryBorderColor | calculated from secondaryColor | Color to be used as border in nodes using `secondaryColor` |
| secondaryTextColor | calculated from secondaryColor | Color to be used as text color in nodes using `secondaryColor` |
| tertiaryColor | calculated from primaryColor | |
| tertiaryBorderColor | calculated from tertiaryColor | Color to be used as border in nodes using `tertiaryColor` |
| tertiaryTextColor | calculated from tertiaryColor | Color to be used as text color in nodes using `tertiaryColor` |
| noteBkgColor | #fff5ad | Color used as background in notes |
| noteTextColor | #333 | Text color in note rectangles |
| noteBorderColor | calculated from noteBkgColor | Border color in note rectangles |
| lineColor | calculated from background | |
| textColor | calculated from primaryTextColor | Text in diagram over the background for instance text on labels and on signals in sequence diagram or the title in Gantt diagram |
| mainBkg | calculated from primaryColor | Background in flowchart objects like rects/circles, class diagram classes, sequence diagram etc |
| errorBkgColor | tertiaryColor | Color for syntax error message |
| errorTextColor | tertiaryTextColor | Color for syntax error message |
> ## Please edit the corresponding file in [/packages/mermaid/src/docs/config/tidy-tree.md](../../packages/mermaid/src/docs/config/tidy-tree.md).
# Tidy-tree Layout
The **tidy-tree** layout arranges nodes in a hierarchical, tree-like structure. It is especially useful for diagrams where parent-child relationships are important, such as mindmaps.
## Features
- Organizes nodes in a tidy, non-overlapping tree
- Ideal for mindmaps and hierarchical data
- Automatically adjusts spacing for readability
## Example Usage
```mermaid-example
---
config:
layout: tidy-tree
---
mindmap
root((mindmap is a long thing))
A
B
C
D
```
```mermaid
---
config:
layout: tidy-tree
---
mindmap
root((mindmap is a long thing))
A
B
C
D
```
```mermaid-example
---
config:
layout: tidy-tree
---
mindmap
root((mindmap))
Origins
Long history
::icon(fa fa-book)
Popularisation
British popular psychology author Tony Buzan
Research
On effectiveness<br/>and features
On Automatic creation
Uses
Creative techniques
Strategic planning
Argument mapping
```
```mermaid
---
config:
layout: tidy-tree
---
mindmap
root((mindmap))
Origins
Long history
::icon(fa fa-book)
Popularisation
British popular psychology author Tony Buzan
Research
On effectiveness<br/>and features
On Automatic creation
Uses
Creative techniques
Strategic planning
Argument mapping
```
## Note
- Currently, tidy-tree is primarily supported for mindmap diagrams.
> ## Please edit the corresponding file in [/packages/mermaid/src/docs/syntax/entityRelationshipDiagram.md](../../packages/mermaid/src/docs/syntax/entityRelationshipDiagram.md).
# Entity Relationship Diagrams
> An entity–relationship model (or ER model) describes interrelated things of interest in a specific domain of knowledge. A basic ER model is composed of entity types (which classify the things of interest) and specifies relationships that can exist between entities (instances of those entity types) [Wikipedia](https://en.wikipedia.org/wiki/Entity%E2%80%93relationship_model).
Note that practitioners of ER modelling almost always refer to _entity types_ simply as _entities_. For example the `CUSTOMER` entity _type_ would be referred to simply as the `CUSTOMER` entity. This is so common it would be inadvisable to do anything else, but technically an entity is an abstract _instance_ of an entity type, and this is what an ER diagram shows - abstract instances, and the relationships between them. This is why entities are always named using singular nouns.
Mermaid can render ER diagrams
```mermaid-example
---
title: Order example
---
erDiagram
CUSTOMER ||--o{ ORDER : places
ORDER ||--|{ LINE-ITEM : contains
CUSTOMER }|..|{ DELIVERY-ADDRESS : uses
```
```mermaid
---
title: Order example
---
erDiagram
CUSTOMER ||--o{ ORDER : places
ORDER ||--|{ LINE-ITEM : contains
CUSTOMER }|..|{ DELIVERY-ADDRESS : uses
```
Entity names are often capitalised, although there is no accepted standard on this, and it is not required in Mermaid.
Relationships between entities are represented by lines with end markers representing cardinality. Mermaid uses the most popular crow's foot notation. The crow's foot intuitively conveys the possibility of many instances of the entity that it connects to.
ER diagrams can be used for various purposes, ranging from abstract logical models devoid of any implementation details, through to physical models of relational database tables. It can be useful to include attribute definitions on ER diagrams to aid comprehension of the purpose and meaning of entities. These do not necessarily need to be exhaustive; often a small subset of attributes is enough. Mermaid allows them to be defined in terms of their _type_ and _name_.
```mermaid-example
erDiagram
CUSTOMER ||--o{ ORDER : places
CUSTOMER {
string name
string custNumber
string sector
}
ORDER ||--|{ LINE-ITEM : contains
ORDER {
int orderNumber
string deliveryAddress
}
LINE-ITEM {
string productCode
int quantity
float pricePerUnit
}
```
```mermaid
erDiagram
CUSTOMER ||--o{ ORDER : places
CUSTOMER {
string name
string custNumber
string sector
}
ORDER ||--|{ LINE-ITEM : contains
ORDER {
int orderNumber
string deliveryAddress
}
LINE-ITEM {
string productCode
int quantity
float pricePerUnit
}
```
When including attributes on ER diagrams, you must decide whether to include foreign keys as attributes. This probably depends on how closely you are trying to represent relational table structures. If your diagram is a _logical_ model which is not meant to imply a relational implementation, then it is better to leave these out because the associative relationships already convey the way that entities are associated. For example, a JSON data structure can implement a one-to-many relationship without the need for foreign key properties, using arrays. Similarly an object-oriented programming language may use pointers or references to collections. Even for models that are intended for relational implementation, you might decide that inclusion of foreign key attributes duplicates information already portrayed by the relationships, and does not add meaning to entities. Ultimately, it's your choice.
## Syntax
### Entities and Relationships
Mermaid syntax for ER diagrams is compatible with PlantUML, with an extension to label the relationship. Each statement consists of the following parts:
- `first-entity` is the name of an entity. Names support any unicode characters and can include spaces if surrounded by double quotes (e.g. "name with space").
- `relationship` describes the way that both entities inter-relate. See below.
- `second-entity` is the name of the other entity.
- `relationship-label` describes the relationship from the perspective of the first entity.
For example:
```
PROPERTY ||--|{ ROOM : contains
```
This statement can be read as _a property contains one or more rooms, and a room is part of one and only one property_. You can see that the label here is from the first entity's perspective: a property contains a room, but a room does not contain a property. When considered from the perspective of the second entity, the equivalent label is usually very easy to infer. (Some ER diagrams label relationships from both perspectives, but this is not supported here, and is usually superfluous).
Only the `first-entity` part of a statement is mandatory. This makes it possible to show an entity with no relationships, which can be useful during iterative construction of diagrams. If any other parts of a statement are specified, then all parts are mandatory.
#### Unicode text
Entity names, relationships, and attributes all support unicode text.
```mermaid-example
erDiagram
"This ❤ Unicode"
```
```mermaid
erDiagram
"This ❤ Unicode"
```
#### Markdown formatting
Markdown formatting and text is also supported.
```mermaid-example
erDiagram
"This **is**_Markdown_"
```
```mermaid
erDiagram
"This **is**_Markdown_"
```
### Relationship Syntax
The `relationship` part of each statement can be broken down into three sub-components:
- the cardinality of the first entity with respect to the second
- whether the relationship confers identity on a 'child' entity
- the cardinality of the second entity with respect to the first
Cardinality is a property that describes how many elements of another entity can be related to the entity in question. In the above example a `PROPERTY` can have one or more `ROOM` instances associated to it, whereas a `ROOM` can only be associated with one `PROPERTY`. In each cardinality marker there are two characters. The outermost character represents a maximum value, and the innermost character represents a minimum value. The table below summarises possible cardinalities.
Relationships may be classified as either _identifying_ or _non-identifying_ and these are rendered with either solid or dashed lines respectively. This is relevant when one of the entities in question cannot have independent existence without the other. For example a firm that insures people to drive cars might need to store data on `NAMED-DRIVER`s. In modelling this we might start out by observing that a `CAR` can be driven by many `PERSON` instances, and a `PERSON` can drive many `CAR`s - both entities can exist without the other, so this is a non-identifying relationship that we might specify in Mermaid as: `PERSON }|..|{ CAR : "driver"`. Note the two dots in the middle of the relationship that will result in a dashed line being drawn between the two entities. But when this many-to-many relationship is resolved into two one-to-many relationships, we observe that a `NAMED-DRIVER` cannot exist without both a `PERSON` and a `CAR` - the relationships become identifying and would be specified using hyphens, which translate to a solid line:
| Value | Alias for |
| :---: | :---------------: |
| -- | _identifying_ |
| .. | _non-identifying_ |
**Aliases**
| Value | Alias for |
| :-----------: | :---------------: |
| to | _identifying_ |
| optionally to | _non-identifying_ |
```mermaid-example
erDiagram
CAR ||--o{ NAMED-DRIVER : allows
PERSON }o..o{ NAMED-DRIVER : is
```
```mermaid
erDiagram
CAR ||--o{ NAMED-DRIVER : allows
PERSON }o..o{ NAMED-DRIVER : is
```
```mermaid-example
erDiagram
CAR 1 to zero or more NAMED-DRIVER : allows
PERSON many(0) optionally to 0+ NAMED-DRIVER : is
```
```mermaid
erDiagram
CAR 1 to zero or more NAMED-DRIVER : allows
PERSON many(0) optionally to 0+ NAMED-DRIVER : is
```
### Attributes
Attributes can be defined for entities by specifying the entity name followed by a block containing multiple `type name` pairs, where a block is delimited by an opening `{` and a closing `}`. The attributes are rendered inside the entity boxes. For example:
```mermaid-example
erDiagram
CAR ||--o{ NAMED-DRIVER : allows
CAR {
string registrationNumber
string make
string model
}
PERSON ||--o{ NAMED-DRIVER : is
PERSON {
string firstName
string lastName
int age
}
```
```mermaid
erDiagram
CAR ||--o{ NAMED-DRIVER : allows
CAR {
string registrationNumber
string make
string model
}
PERSON ||--o{ NAMED-DRIVER : is
PERSON {
string firstName
string lastName
int age
}
```
The `type` values must begin with an alphabetic character and may contain digits, hyphens, underscores, parentheses and square brackets. The `name` values follow a similar format to `type`, but may start with an asterisk as another option to indicate an attribute is a primary key. Other than that, there are no restrictions, and there is no implicit set of valid data types.
### Entity Name Aliases
An alias can be added to an entity using square brackets. If provided, the alias will be showed in the diagram instead of the entity name. Alias names follow all of the same rules as entity names.
```mermaid-example
erDiagram
p[Person] {
string firstName
string lastName
}
a["Customer Account"] {
string email
}
p ||--o| a : has
```
```mermaid
erDiagram
p[Person] {
string firstName
string lastName
}
a["Customer Account"] {
string email
}
p ||--o| a : has
```
#### Attribute Keys and Comments
Attributes may also have a `key` or comment defined. Keys can be `PK`, `FK` or `UK`, for Primary Key, Foreign Key or Unique Key (markdown formatting and unicode is not supported for keys). To specify multiple key constraints on a single attribute, separate them with a comma (e.g., `PK, FK`). A `comment` is defined by double quotes at the end of an attribute. Comments themselves cannot have double-quote characters in them.
```mermaid-example
erDiagram
CAR ||--o{ NAMED-DRIVER : allows
CAR {
string registrationNumber PK
string make
string model
string[] parts
}
PERSON ||--o{ NAMED-DRIVER : is
PERSON {
string driversLicense PK "The license #"
string(99) firstName "Only 99 characters are allowed"
string lastName
string phone UK
int age
}
NAMED-DRIVER {
string carRegistrationNumber PK, FK
string driverLicence PK, FK
}
MANUFACTURER only one to zero or more CAR : makes
```
```mermaid
erDiagram
CAR ||--o{ NAMED-DRIVER : allows
CAR {
string registrationNumber PK
string make
string model
string[] parts
}
PERSON ||--o{ NAMED-DRIVER : is
PERSON {
string driversLicense PK "The license #"
string(99) firstName "Only 99 characters are allowed"
string lastName
string phone UK
int age
}
NAMED-DRIVER {
string carRegistrationNumber PK, FK
string driverLicence PK, FK
}
MANUFACTURER only one to zero or more CAR : makes
```
### Direction
The direction statement declares the direction of the diagram.
This declares that the diagram is oriented from top to bottom (`TB`). This can be reversed to be oriented from bottom to top (`BT`).
```mermaid-example
erDiagram
direction TB
CUSTOMER ||--o{ ORDER : places
CUSTOMER {
string name
string custNumber
string sector
}
ORDER ||--|{ LINE-ITEM : contains
ORDER {
int orderNumber
string deliveryAddress
}
LINE-ITEM {
string productCode
int quantity
float pricePerUnit
}
```
```mermaid
erDiagram
direction TB
CUSTOMER ||--o{ ORDER : places
CUSTOMER {
string name
string custNumber
string sector
}
ORDER ||--|{ LINE-ITEM : contains
ORDER {
int orderNumber
string deliveryAddress
}
LINE-ITEM {
string productCode
int quantity
float pricePerUnit
}
```
This declares that the diagram is oriented from left to right (`LR`). This can be reversed to be oriented from right to left (`RL`).
```mermaid-example
erDiagram
direction LR
CUSTOMER ||--o{ ORDER : places
CUSTOMER {
string name
string custNumber
string sector
}
ORDER ||--|{ LINE-ITEM : contains
ORDER {
int orderNumber
string deliveryAddress
}
LINE-ITEM {
string productCode
int quantity
float pricePerUnit
}
```
```mermaid
erDiagram
direction LR
CUSTOMER ||--o{ ORDER : places
CUSTOMER {
string name
string custNumber
string sector
}
ORDER ||--|{ LINE-ITEM : contains
ORDER {
int orderNumber
string deliveryAddress
}
LINE-ITEM {
string productCode
int quantity
float pricePerUnit
}
```
Possible diagram orientations are:
- TB - Top to bottom
- BT - Bottom to top
- RL - Right to left
- LR - Left to right
### Styling a node
It is possible to apply specific styles such as a thicker border or a different background color to a node.
> **Note:** Custom styles from style or other class statements take priority and will overwrite the default styles. (e.g. The `default` class gives nodes a background color of pink but the `blue` class will give that node a background color of blue if applied.)
```mermaid-example
erDiagram
CAR {
string registrationNumber
string make
string model
}
PERSON {
string firstName
string lastName
int age
}
PERSON:::foo ||--|| CAR : owns
PERSON o{--|| HOUSE:::bar : has
classDef default fill:#f9f,stroke-width:4px
classDef foo stroke:#f00
classDef bar stroke:#0f0
classDef foobar stroke:#00f
```
```mermaid
erDiagram
CAR {
string registrationNumber
string make
string model
}
PERSON {
string firstName
string lastName
int age
}
PERSON:::foo ||--|| CAR : owns
PERSON o{--|| HOUSE:::bar : has
classDef default fill:#f9f,stroke-width:4px
classDef foo stroke:#f00
classDef bar stroke:#0f0
classDef foobar stroke:#00f
```
## Configuration
### Layout
The layout of the diagram is handled by [`render()`](../config/setup/mermaid/interfaces/Mermaid.md#render). The default layout is dagre.
For larger or more-complex diagrams, you can alternatively apply the ELK (Eclipse Layout Kernel) layout using your YAML frontmatter's `config`. For more information, see [Customizing ELK Layout](../intro/syntax-reference.md#customizing-elk-layout).
```yaml
---
config:
layout: elk
---
```
Your Mermaid code should be similar to the following:
```mermaid-example
---
title: Order example
config:
layout: elk
---
erDiagram
CUSTOMER ||--o{ ORDER : places
ORDER ||--|{ LINE-ITEM : contains
CUSTOMER }|..|{ DELIVERY-ADDRESS : uses
```
```mermaid
---
title: Order example
config:
layout: elk
---
erDiagram
CUSTOMER ||--o{ ORDER : places
ORDER ||--|{ LINE-ITEM : contains
CUSTOMER }|..|{ DELIVERY-ADDRESS : uses
```
> **Note**
> Note that the site needs to use mermaid version 9.4+ for this to work and have this featured enabled in the lazy-loading configuration.
> ## Please edit the corresponding file in [/packages/mermaid/src/docs/syntax/gantt.md](../../packages/mermaid/src/docs/syntax/gantt.md).
# Gantt diagrams
> A Gantt chart is a type of bar chart, first developed by Karol Adamiecki in 1896, and independently by Henry Gantt in the 1910s, that illustrates a project schedule and the amount of time it would take for any one project to finish. Gantt charts illustrate number of days between the start and finish dates of the terminal elements and summary elements of a project.
## A note to users
Gantt Charts will record each scheduled task as one continuous bar that extends from the left to the right. The x axis represents time and the y records the different tasks and the order in which they are to be completed.
It is important to remember that when a date, day, or collection of dates specific to a task are "excluded", the Gantt Chart will accommodate those changes by extending an equal number of days, towards the right, not by creating a gap inside the task.
As shown here 
However, if the excluded dates are between two tasks that are set to start consecutively, the excluded dates will be skipped graphically and left blank, and the following task will begin after the end of the excluded dates.
As shown here 
A Gantt chart is useful for tracking the amount of time it would take before a project is finished, but it can also be used to graphically represent "non-working days", with a few tweaks.
Mermaid can render Gantt diagrams as SVG, PNG or a MarkDown link that can be pasted into docs.
```mermaid-example
gantt
title A Gantt Diagram
dateFormat YYYY-MM-DD
section Section
A task :a1, 2014-01-01, 30d
Another task :after a1, 20d
section Another
Task in Another :2014-01-12, 12d
another task :24d
```
```mermaid
gantt
title A Gantt Diagram
dateFormat YYYY-MM-DD
section Section
A task :a1, 2014-01-01, 30d
Another task :after a1, 20d
section Another
Task in Another :2014-01-12, 12d
another task :24d
```
## Syntax
```mermaid-example
gantt
dateFormat YYYY-MM-DD
title Adding GANTT diagram functionality to mermaid
excludes weekends
%% (`excludes` accepts specific dates in YYYY-MM-DD format, days of the week ("sunday") or "weekends", but not the word "weekdays".)
section A section
Completed task :done, des1, 2014-01-06,2014-01-08
Active task :active, des2, 2014-01-09, 3d
Future task : des3, after des2, 5d
Future task2 : des4, after des3, 5d
section Critical tasks
Completed task in the critical line :crit, done, 2014-01-06,24h
Implement parser and jison :crit, done, after des1, 2d
Add another diagram to demo page :doc1, after a1 , 48h
section Last section
Describe gantt syntax :after doc1, 3d
Add gantt diagram to demo page :20h
Add another diagram to demo page :48h
```
Tasks are by default sequential. A task start date defaults to the end date of the preceding task.
A colon, `:`, separates the task title from its metadata.
Metadata items are separated by a comma, `,`. Valid tags are `active`, `done`, `crit`, and `milestone`. Tags are optional, but if used, they must be specified first.
After processing the tags, the remaining metadata items are interpreted as follows:
1. If a single item is specified, it determines when the task ends. It can either be a specific date/time or a duration. If a duration is specified, it is added to the start date of the task to determine the end date of the task, taking into account any exclusions.
2. If two items are specified, the last item is interpreted as in the previous case. The first item can either specify an explicit start date/time (in the format specified by `dateFormat`) or reference another task using `after <otherTaskID> [[otherTaskID2 [otherTaskID3]]...]`. In the latter case, the start date of the task will be set according to the latest end date of any referenced task.
3. If three items are specified, the last two will be interpreted as in the previous case. The first item will denote the ID of the task, which can be referenced using the `later <taskID>` syntax.
| `<taskID>, <startDate>, <endDate>` | `startdate` as interpreted using `dateformat` | `endDate` as interpreted using `dateformat` | `taskID` |
| `<taskID>, <startDate>, <length>` | `startdate` as interpreted using `dateformat` | Start date + `length` | `taskID` |
| `<taskID>, after <otherTaskId>, <endDate>` | End date of previously specified task `otherTaskID` | `endDate` as interpreted using `dateformat` | `taskID` |
| `<taskID>, after <otherTaskId>, <length>` | End date of previously specified task `otherTaskID` | Start date + `length` | `taskID` |
| `<taskID>, <startDate>, until <otherTaskId>` | `startdate` as interpreted using `dateformat` | Start date of previously specified task `otherTaskID` | `taskID` |
| `<taskID>, after <otherTaskId>, until <otherTaskId>` | End date of previously specified task `otherTaskID` | Start date of previously specified task `otherTaskID` | `taskID` |
| `<startDate>, <endDate>` | `startdate` as interpreted using `dateformat` | `enddate` as interpreted using `dateformat` | n/a |
| `<startDate>, <length>` | `startdate` as interpreted using `dateformat` | Start date + `length` | n/a |
| `after <otherTaskID>, <endDate>` | End date of previously specified task `otherTaskID` | `enddate` as interpreted using `dateformat` | n/a |
| `after <otherTaskID>, <length>` | End date of previously specified task `otherTaskID` | Start date + `length` | n/a |
| `<startDate>, until <otherTaskId>` | `startdate` as interpreted using `dateformat` | Start date of previously specified task `otherTaskID` | n/a |
| `after <otherTaskId>, until <otherTaskId>` | End date of previously specified task `otherTaskID` | Start date of previously specified task `otherTaskID` | n/a |
| `<endDate>` | End date of preceding task | `enddate` as interpreted using `dateformat` | n/a |
| `<length>` | End date of preceding task | Start date + `length` | n/a |
| `until <otherTaskId>` | End date of preceding task | Start date of previously specified task `otherTaskID` | n/a |
> **Note**
> Support for keyword `until` was added in (v10.9.0+). This can be used to define a task which is running until some other specific task or milestone starts.
For simplicity, the table does not show the use of multiple tasks listed with the `after` keyword. Here is an example of how to use it and how it's interpreted:
```mermaid-example
gantt
apple :a, 2017-07-20, 1w
banana :crit, b, 2017-07-23, 1d
cherry :active, c, after b a, 1d
kiwi :d, 2017-07-20, until b c
```
```mermaid
gantt
apple :a, 2017-07-20, 1w
banana :crit, b, 2017-07-23, 1d
cherry :active, c, after b a, 1d
kiwi :d, 2017-07-20, until b c
```
### Title
The `title` is an _optional_ string to be displayed at the top of the Gantt chart to describe the chart as a whole.
### Excludes
The `excludes` is an _optional_ attribute that accepts specific dates in YYYY-MM-DD format, days of the week ("sunday") or "weekends", but not the word "weekdays".
These date will be marked on the graph, and be excluded from the duration calculation of tasks. Meaning that if there are excluded dates during a task interval, the number of 'skipped' days will be added to the end of the task to ensure the duration is as specified in the code.
#### Weekend (v\11.0.0+)
When excluding weekends, it is possible to configure the weekends to be either Friday and Saturday or Saturday and Sunday. By default weekends are Saturday and Sunday.
To define the weekend start day, there is an _optional_ attribute `weekend` that can be added in a new line followed by either `friday` or `saturday`.
```mermaid-example
gantt
title A Gantt Diagram Excluding Fri - Sat weekends
dateFormat YYYY-MM-DD
excludes weekends
weekend friday
section Section
A task :a1, 2024-01-01, 30d
Another task :after a1, 20d
```
```mermaid
gantt
title A Gantt Diagram Excluding Fri - Sat weekends
dateFormat YYYY-MM-DD
excludes weekends
weekend friday
section Section
A task :a1, 2024-01-01, 30d
Another task :after a1, 20d
```
### Section statements
You can divide the chart into various sections, for example to separate different parts of a project like development and documentation.
To do so, start a line with the `section` keyword and give it a name. (Note that unlike with the [title for the entire chart](#title), this name is _required_.
### Milestones
You can add milestones to the diagrams. Milestones differ from tasks as they represent a single instant in time and are identified by the keyword `milestone`. Below is an example on how to use milestones. As you may notice, the exact location of the milestone is determined by the initial date for the milestone and the "duration" of the task this way: _initial date_+_duration_/2.
```mermaid-example
gantt
dateFormat HH:mm
axisFormat %H:%M
Initial milestone : milestone, m1, 17:49, 2m
Task A : 10m
Task B : 5m
Final milestone : milestone, m2, 18:08, 4m
```
```mermaid
gantt
dateFormat HH:mm
axisFormat %H:%M
Initial milestone : milestone, m1, 17:49, 2m
Task A : 10m
Task B : 5m
Final milestone : milestone, m2, 18:08, 4m
```
### Vertical Markers
The `vert` keyword lets you add vertical lines to your Gantt chart, making it easy to highlight important dates like deadlines, events, or checkpoints. These markers extend across the entire chart and are positioned based on the date you provide. Unlike milestones, vertical markers don’t take up a row. They’re purely visual reference points that help break up the timeline and make important moments easier to spot.
```mermaid-example
gantt
dateFormat HH:mm
axisFormat %H:%M
Initial vert : vert, v1, 17:30, 2m
Task A : 3m
Task B : 8m
Final vert : vert, v2, 17:58, 4m
```
```mermaid
gantt
dateFormat HH:mm
axisFormat %H:%M
Initial vert : vert, v1, 17:30, 2m
Task A : 3m
Task B : 8m
Final vert : vert, v2, 17:58, 4m
```
## Setting dates
`dateFormat` defines the format of the date **input** of your gantt elements. How these dates are represented in the rendered chart **output** are defined by `axisFormat`.
### Input date format
The default input date format is `YYYY-MM-DD`. You can define your custom `dateFormat`.
More info in: <https://github.com/d3/d3-time#interval_every>
Week-based `tickInterval`s start the week on sunday by default. If you wish to specify another weekday on which the `tickInterval` should start, use the `weekday` option:
```mermaid-example
gantt
tickInterval 1week
weekday monday
```
```mermaid
gantt
tickInterval 1week
weekday monday
```
> **Warning**
> `millisecond` and `second` support was added in v10.3.0
## Output in compact mode
The compact mode allows you to display multiple tasks in the same row. Compact mode can be enabled for a gantt chart by setting the display mode of the graph via preceding YAML settings.
```mermaid-example
---
displayMode: compact
---
gantt
title A Gantt Diagram
dateFormat YYYY-MM-DD
section Section
A task :a1, 2014-01-01, 30d
Another task :a2, 2014-01-20, 25d
Another one :a3, 2014-02-10, 20d
```
```mermaid
---
displayMode: compact
---
gantt
title A Gantt Diagram
dateFormat YYYY-MM-DD
section Section
A task :a1, 2014-01-01, 30d
Another task :a2, 2014-01-20, 25d
Another one :a3, 2014-02-10, 20d
```
## Comments
Comments can be entered within a gantt chart, which will be ignored by the parser. Comments need to be on their own line and must be prefaced with `%%` (double percent signs). Any text after the start of the comment to the next newline will be treated as a comment, including any diagram syntax.
```mermaid-example
gantt
title A Gantt Diagram
%% This is a comment
dateFormat YYYY-MM-DD
section Section
A task :a1, 2014-01-01, 30d
Another task :after a1, 20d
section Another
Task in Another :2014-01-12, 12d
another task :24d
```
```mermaid
gantt
title A Gantt Diagram
%% This is a comment
dateFormat YYYY-MM-DD
section Section
A task :a1, 2014-01-01, 30d
Another task :after a1, 20d
section Another
Task in Another :2014-01-12, 12d
another task :24d
```
## Styling
Styling of the Gantt diagram is done by defining a number of CSS classes. During rendering, these classes are extracted from the file located at src/diagrams/gantt/styles.js
| mirrorActor | Turns on/off the rendering of actors below the diagram as well as above it | false |
| bottomMarginAdj | Adjusts how far down the graph ended. Wide borders styles with css could generate unwanted clipping which is why this config param exists. | 1 |
## Interaction
It is possible to bind a click event to a task. The click can lead to either a javascript callback or to a link which will be opened in the current browser tab. **Note**: This functionality is disabled when using `securityLevel='strict'` and enabled when using `securityLevel='loose'`.
```
click taskId call callback(arguments)
click taskId href URL
```
- taskId is the id of the task
- callback is the name of a javascript function defined on the page displaying the graph, the function will be called with the taskId as the parameter if no other arguments are specified.
Beginner's tip—a full example using interactive links in an HTML context:
> ## Please edit the corresponding file in [/packages/mermaid/src/docs/syntax/kanban.md](../../packages/mermaid/src/docs/syntax/kanban.md).
# Mermaid Kanban Diagram Documentation
Mermaid’s Kanban diagram allows you to create visual representations of tasks moving through different stages of a workflow. This guide explains how to use the Kanban diagram syntax, based on the provided example.
## Overview
A Kanban diagram in Mermaid starts with the kanban keyword, followed by the definition of columns (stages) and tasks within those columns.
```mermaid-example
kanban
column1[Column Title]
task1[Task Description]
```
```mermaid
kanban
column1[Column Title]
task1[Task Description]
```
## Defining Columns
Columns represent the different stages in your workflow, such as “Todo,” “In Progress,” “Done,” etc. Each column is defined using a unique identifier and a title enclosed in square brackets.
**Syntax:**
```
columnId[Column Title]
```
- columnId: A unique identifier for the column.
- \[Column Title]: The title displayed on the column header.
Like this `id1[Todo]`
## Adding Tasks to Columns
Tasks are listed under their respective columns with an indentation. Each task also has a unique identifier and a description enclosed in square brackets.
**Syntax:**
```
taskId[Task Description]
```
```
• taskId: A unique identifier for the task.
• [Task Description]: The description of the task.
```
**Example:**
```
docs[Create Documentation]
```
## Adding Metadata to Tasks
You can include additional metadata for each task using the @{ ... } syntax. Metadata can contain key-value pairs like assigned, ticket, priority, etc. This will be rendered added to the rendering of the node.
## Supported Metadata Keys
```
• assigned: Specifies who is responsible for the task.
• ticket: Links the task to a ticket or issue number.
• priority: Indicates the urgency of the task. Allowed values: 'Very High', 'High', 'Low' and 'Very Low'
You can customize the Kanban diagram using a configuration block at the beginning of your markdown file. This is useful for setting global settings like a base URL for tickets. Currently there is one configuration option for kanban diagrams `ticketBaseUrl`. This can be set as in the following example:
When the kanban item has an assigned ticket number the ticket number in the diagram will have a link to an external system where the ticket is defined. The `ticketBaseUrl` sets the base URL to the external system and #TICKET# is replaced with the ticket value from task metadata to create a valid link.
## Full Example
Below is the full Kanban diagram based on the provided example:
id2[Title of diagram is more than 100 chars when user duplicates diagram with 100 char]@{ ticket: MC-2036, priority: 'Very High'}
id3[Update DB function]@{ ticket: MC-2037, assigned: knsv, priority: 'High' }
id12[Can't reproduce]
id3[Weird flickering in Firefox]
```
In conclusion, creating a Kanban diagram in Mermaid is a straightforward process that effectively visualizes your workflow. Start by using the kanban keyword to initiate the diagram. Define your columns with unique identifiers and titles to represent different stages of your project. Under each column, list your tasks—also with unique identifiers—and provide detailed descriptions as needed. Remember that proper indentation is crucial; tasks must be indented under their parent columns to maintain the correct structure.
You can enhance your diagram by adding optional metadata to tasks using the @{ ... } syntax, which allows you to include additional context such as assignee, ticket numbers, and priority levels. For further customization, utilize the configuration block at the top of your file to set global options like ticketBaseUrl for linking tickets directly from your diagram.
By adhering to these guidelines—ensuring unique identifiers, proper indentation, and utilizing metadata and configuration options—you can create a comprehensive and customized Kanban board that effectively maps out your project’s workflow using Mermaid.
> ## Please edit the corresponding file in [/packages/mermaid/src/docs/syntax/mindmap.md](../../packages/mermaid/src/docs/syntax/mindmap.md).
# Mindmap
> Mindmap: This is an experimental diagram for now. The syntax and properties can change in future releases. The syntax is stable except for the icon integration which is the experimental part.
"A mind map is a diagram used to visually organize information into a hierarchy, showing relationships among pieces of the whole. It is often created around a single concept, drawn as an image in the center of a blank page, to which associated representations of ideas such as images, words and parts of words are added. Major ideas are connected directly to the central concept, and other ideas branch out from those major ideas." Wikipedia
### An example of a mindmap.
```mermaid-example
mindmap
root((mindmap))
Origins
Long history
::icon(fa fa-book)
Popularisation
British popular psychology author Tony Buzan
Research
On effectiveness<br/>and features
On Automatic creation
Uses
Creative techniques
Strategic planning
Argument mapping
Tools
Pen and paper
Mermaid
```
```mermaid
mindmap
root((mindmap))
Origins
Long history
::icon(fa fa-book)
Popularisation
British popular psychology author Tony Buzan
Research
On effectiveness<br/>and features
On Automatic creation
Uses
Creative techniques
Strategic planning
Argument mapping
Tools
Pen and paper
Mermaid
```
## Syntax
The syntax for creating Mindmaps is simple and relies on indentation for setting the levels in the hierarchy.
In the following example you can see how there are 3 different levels. One with starting at the left of the text and another level with two rows starting at the same column, defining the node A. At the end there is one more level where the text is indented further than the previous lines defining the nodes B and C.
```
mindmap
Root
A
B
C
```
In summary is a simple text outline where there is one node at the root level called `Root` which has one child `A`. `A` in turn has two children `B`and `C`. In the diagram below we can see this rendered as a mindmap.
```mermaid-example
mindmap
Root
A
B
C
```
```mermaid
mindmap
Root
A
B
C
```
In this way we can use a text outline to generate a hierarchical mindmap.
## Different shapes
Mermaid mindmaps can show nodes using different shapes. When specifying a shape for a node the syntax is similar to flowchart nodes, with an id followed by the shape definition and with the text within the shape delimiters. Where possible we try/will try to keep the same shapes as for flowcharts, even though they are not all supported from the start.
Mindmap can show the following shapes:
### Square
```mermaid-example
mindmap
id[I am a square]
```
```mermaid
mindmap
id[I am a square]
```
### Rounded square
```mermaid-example
mindmap
id(I am a rounded square)
```
```mermaid
mindmap
id(I am a rounded square)
```
### Circle
```mermaid-example
mindmap
id((I am a circle))
```
```mermaid
mindmap
id((I am a circle))
```
### Bang
```mermaid-example
mindmap
id))I am a bang((
```
```mermaid
mindmap
id))I am a bang((
```
### Cloud
```mermaid-example
mindmap
id)I am a cloud(
```
```mermaid
mindmap
id)I am a cloud(
```
### Hexagon
```mermaid-example
mindmap
id{{I am a hexagon}}
```
```mermaid
mindmap
id{{I am a hexagon}}
```
### Default
```mermaid-example
mindmap
I am the default shape
```
```mermaid
mindmap
I am the default shape
```
More shapes will be added, beginning with the shapes available in flowcharts.
# Icons and classes
## Icons
As with flowcharts you can add icons to your nodes but with an updated syntax. The styling for the font based icons are added during the integration so that they are available for the web page. _This is not something a diagram author can do but has to be done with the site administrator or the integrator_. Once the icon fonts are in place you add them to the mind map nodes using the `::icon()` syntax. You place the classes for the icon within the parenthesis like in the following example where icons for material design and [Font Awesome 5](https://fontawesome.com/v5/search?o=r&m=free) are displayed. The intention is that this approach should be used for all diagrams supporting icons. **Experimental feature:** This wider scope is also the reason Mindmaps are experimental as this syntax and approach could change.
```mermaid-example
mindmap
Root
A
::icon(fa fa-book)
B(B)
::icon(mdi mdi-skull-outline)
```
```mermaid
mindmap
Root
A
::icon(fa fa-book)
B(B)
::icon(mdi mdi-skull-outline)
```
## Classes
Again the syntax for adding classes is similar to flowcharts. You can add classes using a triple colon following a number of css classes separated by space. In the following example one of the nodes has two custom classes attached urgent turning the background red and the text white and large increasing the font size:
```mermaid-example
mindmap
Root
A[A]
:::urgent large
B(B)
C
```
```mermaid
mindmap
Root
A[A]
:::urgent large
B(B)
C
```
_These classes need to be supplied by the site administrator._
## Unclear indentation
The actual indentation does not really matter only compared with the previous rows. If we take the previous example and disrupt it a little we can see how the calculations are performed. Let us start with placing C with a smaller indentation than `B` but larger then `A`.
```
mindmap
Root
A
B
C
```
This outline is unclear as `B` clearly is a child of `A` but when we move on to `C` the clarity is lost. `C` is neither a child of `B` with a higher indentation nor does it have the same indentation as `B`. The only thing that is clear is that the first node with smaller indentation, indicating a parent, is A. Then Mermaid relies on this known truth and compensates for the unclear indentation and selects `A` as a parent of `C` leading till the same diagram with `B` and `C` as siblings.
```mermaid-example
mindmap
Root
A
B
C
```
```mermaid
mindmap
Root
A
B
C
```
## Markdown Strings
The "Markdown Strings" feature enhances mind maps by offering a more versatile string type, which supports text formatting options such as bold and italics, and automatically wraps text within labels.
```mermaid-example
mindmap
id1["`**Root** with
a second line
Unicode works too: 🤓`"]
id2["`The dog in **the** hog... a *very long text* that wraps to a new line`"]
id3[Regular labels still works]
```
```mermaid
mindmap
id1["`**Root** with
a second line
Unicode works too: 🤓`"]
id2["`The dog in **the** hog... a *very long text* that wraps to a new line`"]
id3[Regular labels still works]
```
Formatting:
- For bold text, use double asterisks \*\* before and after the text.
- For italics, use single asterisks \* before and after the text.
- With traditional strings, you needed to add <br> tags for text to wrap in nodes. However, markdown strings automatically wrap text when it becomes too long and allows you to start a new line by simply using a newline character instead of a <br> tag.
## Integrating with your library/website.
Mindmap uses the experimental lazy loading & async rendering features which could change in the future. From version 9.4.0 this diagram is included in mermaid but use lazy loading in order to keep the size of mermaid down. This is important in order to be able to add additional diagrams going forward.
You can still use the pre 9.4.0 method to add mermaid with mindmaps to a web page:
```html
<script type="module">
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@9.3.0/dist/mermaid.esm.min.mjs';
import mindmap from 'https://cdn.jsdelivr.net/npm/@mermaid-js/mermaid-mindmap@9.3.0/dist/mermaid-mindmap.esm.min.mjs';
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs';
</script>
```
You can also refer the [implementation in the live editor](https://github.com/mermaid-js/mermaid-live-editor/blob/develop/src/lib/util/mermaid.ts) to see how the async loading is done.
<!---
cspell:locale en,en-gb
cspell:ignore Buzan
--->
## Layouts
Mermaid also supports a Tidy Tree layout for mindmaps.
```
---
config:
layout: tidy-tree
---
mindmap
root((mindmap is a long thing))
A
B
C
D
```
Instructions to add and register tidy-tree layout are present in [Tidy Tree Configuration](/config/tidy-tree)
> ## Please edit the corresponding file in [/packages/mermaid/src/docs/syntax/packet.md](../../packages/mermaid/src/docs/syntax/packet.md).
# Packet Diagram (v11.0.0+)
## Introduction
A packet diagram is a visual representation used to illustrate the structure and contents of a network packet. Network packets are the fundamental units of data transferred over a network.
## Usage
This diagram type is particularly useful for developers, network engineers, educators, and students who require a clear and concise way to represent the structure of network packets.
## Syntax
```
packet
start: "Block name" %% Single-bit block
start-end: "Block name" %% Multi-bit blocks
... More Fields ...
```
### Bits Syntax (v11.7.0+)
Using start and end bit counts can be difficult, especially when modifying a design. For this we add a bit count field, which starts from the end of the previous field automagically. Use `+<count>` to set the number of bits, thus:
```
packet
+1: "Block name" %% Single-bit block
+8: "Block name" %% 8-bit block
9-15: "Manually set start and end, it's fine to mix and match"
... More Fields ...
```
## Examples
```mermaid-example
---
title: "TCP Packet"
---
packet
0-15: "Source Port"
16-31: "Destination Port"
32-63: "Sequence Number"
64-95: "Acknowledgment Number"
96-99: "Data Offset"
100-105: "Reserved"
106: "URG"
107: "ACK"
108: "PSH"
109: "RST"
110: "SYN"
111: "FIN"
112-127: "Window"
128-143: "Checksum"
144-159: "Urgent Pointer"
160-191: "(Options and Padding)"
192-255: "Data (variable length)"
```
```mermaid
---
title: "TCP Packet"
---
packet
0-15: "Source Port"
16-31: "Destination Port"
32-63: "Sequence Number"
64-95: "Acknowledgment Number"
96-99: "Data Offset"
100-105: "Reserved"
106: "URG"
107: "ACK"
108: "PSH"
109: "RST"
110: "SYN"
111: "FIN"
112-127: "Window"
128-143: "Checksum"
144-159: "Urgent Pointer"
160-191: "(Options and Padding)"
192-255: "Data (variable length)"
```
```mermaid-example
packet
title UDP Packet
+16: "Source Port"
+16: "Destination Port"
32-47: "Length"
48-63: "Checksum"
64-95: "Data (variable length)"
```
```mermaid
packet
title UDP Packet
+16: "Source Port"
+16: "Destination Port"
32-47: "Length"
48-63: "Checksum"
64-95: "Data (variable length)"
```
## Details of Syntax
- **Ranges**: Each line after the title represents a different field in the packet. The range (e.g., `0-15`) indicates the bit positions in the packet.
- **Field Description**: A brief description of what the field represents, enclosed in quotes.
## Configuration
Please refer to the [configuration](/config/schema-docs/config-defs-packet-diagram-config.html) guide for details.
<!--
Theme variables are not currently working due to a mermaid bug. The passed values are not being propagated into styles function.
> ## Please edit the corresponding file in [/packages/mermaid/src/docs/syntax/pie.md](../../packages/mermaid/src/docs/syntax/pie.md).
# Pie chart diagrams
> A pie chart (or a circle chart) is a circular statistical graphic, which is divided into slices to illustrate numerical proportion. In a pie chart, the arc length of each slice (and consequently its central angle and area), is proportional to the quantity it represents. While it is named for its resemblance to a pie which has been sliced, there are variations on the way it can be presented. The earliest known pie chart is generally credited to William Playfair's Statistical Breviary of 1801
> -Wikipedia
Mermaid can render Pie Chart diagrams.
```mermaid-example
pie title Pets adopted by volunteers
"Dogs" : 386
"Cats" : 85
"Rats" : 15
```
```mermaid
pie title Pets adopted by volunteers
"Dogs" : 386
"Cats" : 85
"Rats" : 15
```
## Syntax
Drawing a pie chart is really simple in mermaid.
- Start with `pie` keyword to begin the diagram
- `showData` to render the actual data values after the legend text. This is **_OPTIONAL_**
- Followed by `title` keyword and its value in string to give a title to the pie-chart. This is **_OPTIONAL_**
- Followed by dataSet. Pie slices will be ordered clockwise in the same order as the labels.
- `label` for a section in the pie diagram within `" "` quotes.
- Followed by `:` colon as separator
- Followed by `positive numeric value` (supported up to two decimal places)
**Note:**
> Pie chart values must be **positive numbers greater than zero**.
> **Negative values are not allowed** and will result in an error.
> ## Please edit the corresponding file in [/packages/mermaid/src/docs/syntax/quadrantChart.md](../../packages/mermaid/src/docs/syntax/quadrantChart.md).
# Quadrant Chart
> A quadrant chart is a visual representation of data that is divided into four quadrants. It is used to plot data points on a two-dimensional grid, with one variable represented on the x-axis and another variable represented on the y-axis. The quadrants are determined by dividing the chart into four equal parts based on a set of criteria that is specific to the data being analyzed. Quadrant charts are often used to identify patterns and trends in data, and to prioritize actions based on the position of data points within the chart. They are commonly used in business, marketing, and risk management, among other fields.
## Example
```mermaid-example
quadrantChart
title Reach and engagement of campaigns
x-axis Low Reach --> High Reach
y-axis Low Engagement --> High Engagement
quadrant-1 We should expand
quadrant-2 Need to promote
quadrant-3 Re-evaluate
quadrant-4 May be improved
Campaign A: [0.3, 0.6]
Campaign B: [0.45, 0.23]
Campaign C: [0.57, 0.69]
Campaign D: [0.78, 0.34]
Campaign E: [0.40, 0.34]
Campaign F: [0.35, 0.78]
```
```mermaid
quadrantChart
title Reach and engagement of campaigns
x-axis Low Reach --> High Reach
y-axis Low Engagement --> High Engagement
quadrant-1 We should expand
quadrant-2 Need to promote
quadrant-3 Re-evaluate
quadrant-4 May be improved
Campaign A: [0.3, 0.6]
Campaign B: [0.45, 0.23]
Campaign C: [0.57, 0.69]
Campaign D: [0.78, 0.34]
Campaign E: [0.40, 0.34]
Campaign F: [0.35, 0.78]
```
## Syntax
> **Note**
> If there are no points available in the chart both **axis** text and **quadrant** will be rendered in the center of the respective quadrant.
> If there are points **x-axis** labels will rendered from the left of the respective quadrant also they will be displayed at the bottom of the chart, and **y-axis** labels will be rendered at the bottom of the respective quadrant, the quadrant text will render at the top of the respective quadrant.
> **Note**
> For points x and y value min value is 0 and max value is 1.
### Title
The title is a short description of the chart and it will always render on top of the chart.
#### Example
```
quadrantChart
title This is a sample example
```
### x-axis
The x-axis determines what text would be displayed in the x-axis. In x-axis there is two part **left** and **right** you can pass **both** or you can pass only **left**. The statement should start with `x-axis` then the `left axis text` followed by the delimiter `-->` then `right axis text`.
#### Example
1. `x-axis <text> --> <text>` both the left and right axis text will be rendered.
2. `x-axis <text>` only the left axis text will be rendered.
### y-axis
The y-axis determines what text would be displayed in the y-axis. In y-axis there is two part **top** and **bottom** you can pass **both** or you can pass only **bottom**. The statement should start with `y-axis` then the `bottom axis text` followed by the delimiter `-->` then `top axis text`.
#### Example
1. `y-axis <text> --> <text>` both the bottom and top axis text will be rendered.
2. `y-axis <text>` only the bottom axis text will be rendered.
### Quadrants text
The `quadrant-[1,2,3,4]` determine what text would be displayed inside the quadrants.
#### Example
1. `quadrant-1 <text>` determine what text will be rendered inside the top right quadrant.
2. `quadrant-2 <text>` determine what text will be rendered inside the top left quadrant.
3. `quadrant-3 <text>` determine what text will be rendered inside the bottom left quadrant.
4. `quadrant-4 <text>` determine what text will be rendered inside the bottom right quadrant.
### Points
Points are used to plot a circle inside the quadrantChart. The syntax is `<text>: [x, y]` here x and y value is in the range 0 - 1.
#### Example
1. `Point 1: [0.75, 0.80]` here the Point 1 will be drawn in the top right quadrant.
2. `Point 2: [0.35, 0.24]` here the Point 2 will be drawn in the bottom left quadrant.
> ## Please edit the corresponding file in [/packages/mermaid/src/docs/syntax/radar.md](../../packages/mermaid/src/docs/syntax/radar.md).
# Radar Diagram (v11.6.0+)
## Introduction
A radar diagram is a simple way to plot low-dimensional data in a circular format.
It is also known as a **radar chart**, **spider chart**, **star chart**, **cobweb chart**, **polar chart**, or **Kiviat diagram**.
## Usage
This diagram type is particularly useful for developers, data scientists, and engineers who require a clear and concise way to represent data in a circular format.
It is commonly used to graphically summarize and compare the performance of multiple entities across multiple dimensions.
`title`: The title is an optional field that allows to render a title at the top of the radar diagram.
```
radar-beta
title Title of the Radar Diagram
...
```
### Axis
`axis`: The axis keyword is used to define the axes of the radar diagram.
Each axis is represented by an ID and an optional label.
Multiple axes can be defined in a single line.
```
radar-beta
axis id1["Label1"]
axis id2["Label2"], id3["Label3"]
...
```
### Curve
`curve`: The curve keyword is used to define the data points for a curve in the radar diagram.
Each curve is represented by an ID, an optional label, and a list of values.
Values can be defined by a list of numbers or a list of key-value pairs. If key-value pairs are used, the key represents the axis ID and the value represents the data point. Else, the data points are assumed to be in the order of the axes defined.
Multiple curves can be defined in a single line.
```
radar-beta
axis axis1, axis2, axis3
curve id1["Label1"]{1, 2, 3}
curve id2["Label2"]{4, 5, 6}, id3{7, 8, 9}
curve id4{ axis3: 30, axis1: 20, axis2: 10 }
...
```
### Options
- `showLegend`: The showLegend keyword is used to show or hide the legend in the radar diagram. The legend is shown by default.
- `max`: The maximum value for the radar diagram. This is used to scale the radar diagram. If not provided, the maximum value is calculated from the data points.
- `min`: The minimum value for the radar diagram. This is used to scale the radar diagram. If not provided, the minimum value is `0`.
- `graticule`: The graticule keyword is used to define the type of graticule to be rendered in the radar diagram. The graticule can be `circle` or `polygon`. If not provided, the default graticule is `circle`.
- `ticks`: The ticks keyword is used to define the number of ticks on the graticule. It is the number of concentric circles or polygons drawn to indicate the scale of the radar diagram. If not provided, the default number of ticks is `5`.
```
radar-beta
...
showLegend true
max 100
min 0
graticule circle
ticks 5
...
```
## Configuration
Please refer to the [configuration](/config/schema-docs/config-defs-radar-diagram-config.html) guide for details.
| marginTop | Top margin of the radar diagram | `50` |
| marginBottom | Bottom margin of the radar diagram | `50` |
| marginLeft | Left margin of the radar diagram | `50` |
| marginRight | Right margin of the radar diagram | `50` |
| axisScaleFactor | Scale factor for the axis | `1` |
| axisLabelFactor | Factor to adjust the axis label position | `1.05` |
| curveTension | Tension for the rounded curves | `0.17` |
## Theme Variables
### Global Theme Variables
> **Note**
> The default values for these variables depend on the theme used. To override the default values, set the desired values in the themeVariables section of the configuration:
>
> ---
>
> config:
> themeVariables:
> cScale0: "#FF0000"
> cScale1: "#00FF00"
>
> ---
Radar charts support the color scales `cScale${i}` where `i` is a number from `0` to the theme's maximum number of colors in its color scale. Usually, the maximum number of colors is `12`.
| Property | Description |
| ---------- | ------------------------------ |
| fontSize | Font size of the title |
| titleColor | Color of the title |
| cScale${i} | Color scale for the i-th curve |
### Radar Style Options
> **Note**
> Specific variables for radar resides inside the `radar` key. To set the radar style options, use this syntax.
> ## Please edit the corresponding file in [/packages/mermaid/src/docs/syntax/requirementDiagram.md](../../packages/mermaid/src/docs/syntax/requirementDiagram.md).
# Requirement Diagram
> A Requirement diagram provides a visualization for requirements and their connections, to each other and other documented elements. The modeling specs follow those defined by SysML v1.6.
Rendering requirements is straightforward.
```mermaid-example
requirementDiagram
requirement test_req {
id: 1
text: the test text.
risk: high
verifymethod: test
}
element test_entity {
type: simulation
}
test_entity - satisfies -> test_req
```
```mermaid
requirementDiagram
requirement test_req {
id: 1
text: the test text.
risk: high
verifymethod: test
}
element test_entity {
type: simulation
}
test_entity - satisfies -> test_req
```
## Syntax
There are three types of components to a requirement diagram: requirement, element, and relationship.
The grammar for defining each is defined below. Words denoted in angle brackets, such as `<word>`, are enumerated keywords that have options elaborated in a table. `user_defined_...` is use in any place where user input is expected.
An important note on user text: all input can be surrounded in quotes or not. For example, both `id: "here is an example"` and `id: here is an example` are both valid. However, users must be careful with unquoted input. The parser will fail if another keyword is detected.
### Requirement
A requirement definition contains a requirement type, name, id, text, risk, and verification method. The syntax follows:
```
<type> user_defined_name {
id: user_defined_id
text: user_defined text
risk: <risk>
verifymethod: <method>
}
```
Type, risk, and method are enumerations defined in SysML.
An element definition contains an element name, type, and document reference. These three are all user defined. The element feature is intended to be lightweight but allow requirements to be connected to portions of other documents.
```
element user_defined_name {
type: user_defined_type
docref: user_defined_ref
}
```
### Markdown Formatting
In places where user defined text is possible (like names, requirement text, element docref, etc.), you can:
- Surround the text in quotes: `"example text"`
- Use markdown formatting inside quotes: `"**bold text** and *italics*"`
Example:
```mermaid-example
requirementDiagram
requirement "__test_req__" {
id: 1
text: "*italicized text* **bold text**"
risk: high
verifymethod: test
}
```
```mermaid
requirementDiagram
requirement "__test_req__" {
id: 1
text: "*italicized text* **bold text**"
risk: high
verifymethod: test
}
```
### Relationship
Relationships are comprised of a source node, destination node, and relationship type.
Each follows the definition format of
```
{name of source} - <type> -> {name of destination}
```
or
```
{name of destination} <- <type> - {name of source}
```
"name of source" and "name of destination" should be names of requirement or element nodes defined elsewhere.
A relationship type can be one of contains, copies, derives, satisfies, verifies, refines, or traces.
Each relationship is labeled in the diagram.
## Larger Example
This example uses all features of the diagram.
```mermaid-example
requirementDiagram
requirement test_req {
id: 1
text: the test text.
risk: high
verifymethod: test
}
functionalRequirement test_req2 {
id: 1.1
text: the second test text.
risk: low
verifymethod: inspection
}
performanceRequirement test_req3 {
id: 1.2
text: the third test text.
risk: medium
verifymethod: demonstration
}
interfaceRequirement test_req4 {
id: 1.2.1
text: the fourth test text.
risk: medium
verifymethod: analysis
}
physicalRequirement test_req5 {
id: 1.2.2
text: the fifth test text.
risk: medium
verifymethod: analysis
}
designConstraint test_req6 {
id: 1.2.3
text: the sixth test text.
risk: medium
verifymethod: analysis
}
element test_entity {
type: simulation
}
element test_entity2 {
type: word doc
docRef: reqs/test_entity
}
element test_entity3 {
type: "test suite"
docRef: github.com/all_the_tests
}
test_entity - satisfies -> test_req2
test_req - traces -> test_req2
test_req - contains -> test_req3
test_req3 - contains -> test_req4
test_req4 - derives -> test_req5
test_req5 - refines -> test_req6
test_entity3 - verifies -> test_req5
test_req <- copies - test_entity2
```
```mermaid
requirementDiagram
requirement test_req {
id: 1
text: the test text.
risk: high
verifymethod: test
}
functionalRequirement test_req2 {
id: 1.1
text: the second test text.
risk: low
verifymethod: inspection
}
performanceRequirement test_req3 {
id: 1.2
text: the third test text.
risk: medium
verifymethod: demonstration
}
interfaceRequirement test_req4 {
id: 1.2.1
text: the fourth test text.
risk: medium
verifymethod: analysis
}
physicalRequirement test_req5 {
id: 1.2.2
text: the fifth test text.
risk: medium
verifymethod: analysis
}
designConstraint test_req6 {
id: 1.2.3
text: the sixth test text.
risk: medium
verifymethod: analysis
}
element test_entity {
type: simulation
}
element test_entity2 {
type: word doc
docRef: reqs/test_entity
}
element test_entity3 {
type: "test suite"
docRef: github.com/all_the_tests
}
test_entity - satisfies -> test_req2
test_req - traces -> test_req2
test_req - contains -> test_req3
test_req3 - contains -> test_req4
test_req4 - derives -> test_req5
test_req5 - refines -> test_req6
test_entity3 - verifies -> test_req5
test_req <- copies - test_entity2
```
## Direction
The diagram can be rendered in different directions using the `direction` statement. Valid values are:
- `TB` - Top to Bottom (default)
- `BT` - Bottom to Top
- `LR` - Left to Right
- `RL` - Right to Left
Example:
```mermaid-example
requirementDiagram
direction LR
requirement test_req {
id: 1
text: the test text.
risk: high
verifymethod: test
}
element test_entity {
type: simulation
}
test_entity - satisfies -> test_req
```
```mermaid
requirementDiagram
direction LR
requirement test_req {
id: 1
text: the test text.
risk: high
verifymethod: test
}
element test_entity {
type: simulation
}
test_entity - satisfies -> test_req
```
## Styling
Requirements and elements can be styled using direct styling or classes. As a rule of thumb, when applying styles or classes, it accepts a list of requirement or element names and a list of class names allowing multiple assignments at a time (The only exception is the shorthand syntax `:::` which can assign multiple classes but only to one requirement or element at a time).
### Direct Styling
Use the `style` keyword to apply CSS styles directly:
```mermaid-example
requirementDiagram
requirement test_req {
id: 1
text: styling example
risk: low
verifymethod: test
}
element test_entity {
type: simulation
}
style test_req fill:#ffa,stroke:#000, color: green
style test_entity fill:#f9f,stroke:#333, color: blue
```
```mermaid
requirementDiagram
requirement test_req {
id: 1
text: styling example
risk: low
verifymethod: test
}
element test_entity {
type: simulation
}
style test_req fill:#ffa,stroke:#000, color: green
style test_entity fill:#f9f,stroke:#333, color: blue
```
### Class Definitions
Define reusable styles using `classDef`:
```mermaid-example
requirementDiagram
requirement test_req {
id: 1
text: "class styling example"
risk: low
verifymethod: test
}
element test_entity {
type: simulation
}
classDef important fill:#f96,stroke:#333,stroke-width:4px
classDef test fill:#ffa,stroke:#000
```
```mermaid
requirementDiagram
requirement test_req {
id: 1
text: "class styling example"
risk: low
verifymethod: test
}
element test_entity {
type: simulation
}
classDef important fill:#f96,stroke:#333,stroke-width:4px
classDef test fill:#ffa,stroke:#000
```
### Default class
If a class is named default it will be applied to all nodes. Specific styles and classes should be defined afterwards to override the applied default styling.
> ## Please edit the corresponding file in [/packages/mermaid/src/docs/syntax/sankey.md](../../packages/mermaid/src/docs/syntax/sankey.md).
# Sankey diagram (v10.3.0+)
> A sankey diagram is a visualization used to depict a flow from one set of values to another.
> **Warning**
> This is an experimental diagram. Its syntax are very close to plain CSV, but it is to be extended in the nearest future.
The things being connected are called nodes and the connections are called links.
## Example
This example taken from [observable](https://observablehq.com/@d3/sankey/2?collection=@d3/d3-sankey). It may be rendered a little bit differently, though, in terms of size and colors.
```mermaid-example
---
config:
sankey:
showValues: false
---
sankey
Agricultural 'waste',Bio-conversion,124.729
Bio-conversion,Liquid,0.597
Bio-conversion,Losses,26.862
Bio-conversion,Solid,280.322
Bio-conversion,Gas,81.144
Biofuel imports,Liquid,35
Biomass imports,Solid,35
Coal imports,Coal,11.606
Coal reserves,Coal,63.965
Coal,Solid,75.571
District heating,Industry,10.639
District heating,Heating and cooling - commercial,22.505
District heating,Heating and cooling - homes,46.184
> ## Please edit the corresponding file in [/packages/mermaid/src/docs/syntax/stateDiagram.md](../../packages/mermaid/src/docs/syntax/stateDiagram.md).
# State diagrams
> "A state diagram is a type of diagram used in computer science and related fields to describe the behavior of systems.
> State diagrams require that the system described is composed of a finite number of states; sometimes, this is indeed the
> case, while at other times this is a reasonable abstraction." Wikipedia
Mermaid can render state diagrams. The syntax tries to be compliant with the syntax used in plantUml as this will make
it easier for users to share diagrams between mermaid and plantUml.
```mermaid-example
---
title: Simple sample
---
stateDiagram-v2
[*] --> Still
Still --> [*]
Still --> Moving
Moving --> Still
Moving --> Crash
Crash --> [*]
```
```mermaid
---
title: Simple sample
---
stateDiagram-v2
[*] --> Still
Still --> [*]
Still --> Moving
Moving --> Still
Moving --> Crash
Crash --> [*]
```
Older renderer:
```mermaid-example
stateDiagram
[*] --> Still
Still --> [*]
Still --> Moving
Moving --> Still
Moving --> Crash
Crash --> [*]
```
```mermaid
stateDiagram
[*] --> Still
Still --> [*]
Still --> Moving
Moving --> Still
Moving --> Crash
Crash --> [*]
```
In state diagrams systems are described in terms of _states_ and how one _state_ can change to another _state_ via
a _transition._ The example diagram above shows three states: **Still**, **Moving** and **Crash**. You start in the
**Still** state. From **Still** you can change to the **Moving** state. From **Moving** you can change either back to the **Still** state or to
the **Crash** state. There is no transition from **Still** to **Crash**. (You can't crash if you're still.)
## States
A state can be declared in multiple ways. The simplest way is to define a state with just an id:
```mermaid-example
stateDiagram-v2
stateId
```
```mermaid
stateDiagram-v2
stateId
```
Another way is by using the state keyword with a description as per below:
```mermaid-example
stateDiagram-v2
state "This is a state description" as s2
```
```mermaid
stateDiagram-v2
state "This is a state description" as s2
```
Another way to define a state with a description is to define the state id followed by a colon and the description:
```mermaid-example
stateDiagram-v2
s2 : This is a state description
```
```mermaid
stateDiagram-v2
s2 : This is a state description
```
## Transitions
Transitions are path/edges when one state passes into another. This is represented using text arrow, "-->".
When you define a transition between two states and the states are not already defined, the undefined states are defined
with the id from the transition. You can later add descriptions to states defined this way.
```mermaid-example
stateDiagram-v2
s1 --> s2
```
```mermaid
stateDiagram-v2
s1 --> s2
```
It is possible to add text to a transition to describe what it represents:
```mermaid-example
stateDiagram-v2
s1 --> s2: A transition
```
```mermaid
stateDiagram-v2
s1 --> s2: A transition
```
## Start and End
There are two special states indicating the start and stop of the diagram. These are written with the \[\*] syntax and
the direction of the transition to it defines it either as a start or a stop state.
```mermaid-example
stateDiagram-v2
[*] --> s1
s1 --> [*]
```
```mermaid
stateDiagram-v2
[*] --> s1
s1 --> [*]
```
## Composite states
In a real world use of state diagrams you often end up with diagrams that are multidimensional as one state can
have several internal states. These are called composite states in this terminology.
In order to define a composite state you need to use the state keyword followed by an id and the body of the composite
state between {}. You can name a composite state on a separate line just like a simple state. See the example below:
```mermaid-example
stateDiagram-v2
[*] --> First
state First {
[*] --> second
second --> [*]
}
[*] --> NamedComposite
NamedComposite: Another Composite
state NamedComposite {
[*] --> namedSimple
namedSimple --> [*]
namedSimple: Another simple
}
```
```mermaid
stateDiagram-v2
[*] --> First
state First {
[*] --> second
second --> [*]
}
[*] --> NamedComposite
NamedComposite: Another Composite
state NamedComposite {
[*] --> namedSimple
namedSimple --> [*]
namedSimple: Another simple
}
```
You can do this in several layers:
```mermaid-example
stateDiagram-v2
[*] --> First
state First {
[*] --> Second
state Second {
[*] --> second
second --> Third
state Third {
[*] --> third
third --> [*]
}
}
}
```
```mermaid
stateDiagram-v2
[*] --> First
state First {
[*] --> Second
state Second {
[*] --> second
second --> Third
state Third {
[*] --> third
third --> [*]
}
}
}
```
You can also define transitions also between composite states:
```mermaid-example
stateDiagram-v2
[*] --> First
First --> Second
First --> Third
state First {
[*] --> fir
fir --> [*]
}
state Second {
[*] --> sec
sec --> [*]
}
state Third {
[*] --> thi
thi --> [*]
}
```
```mermaid
stateDiagram-v2
[*] --> First
First --> Second
First --> Third
state First {
[*] --> fir
fir --> [*]
}
state Second {
[*] --> sec
sec --> [*]
}
state Third {
[*] --> thi
thi --> [*]
}
```
_You cannot define transitions between internal states belonging to different composite states_
## Choice
Sometimes you need to model a choice between two or more paths, you can do so using <\<choice>>.
```mermaid-example
stateDiagram-v2
state if_state <<choice>>
[*] --> IsPositive
IsPositive --> if_state
if_state --> False: if n < 0
if_state --> True : if n >= 0
```
```mermaid
stateDiagram-v2
state if_state <<choice>>
[*] --> IsPositive
IsPositive --> if_state
if_state --> False: if n < 0
if_state --> True : if n >= 0
```
## Forks
It is possible to specify a fork in the diagram using <\<fork>> <\<join>>.
```mermaid-example
stateDiagram-v2
state fork_state <<fork>>
[*] --> fork_state
fork_state --> State2
fork_state --> State3
state join_state <<join>>
State2 --> join_state
State3 --> join_state
join_state --> State4
State4 --> [*]
```
```mermaid
stateDiagram-v2
state fork_state <<fork>>
[*] --> fork_state
fork_state --> State2
fork_state --> State3
state join_state <<join>>
State2 --> join_state
State3 --> join_state
join_state --> State4
State4 --> [*]
```
## Notes
Sometimes nothing says it better than a Post-it note. That is also the case in state diagrams.
Here you can choose to put the note to the _right of_ or to the _left of_ a node.
```mermaid-example
stateDiagram-v2
State1: The state with a note
note right of State1
Important information! You can write
notes.
end note
State1 --> State2
note left of State2 : This is the note to the left.
```
```mermaid
stateDiagram-v2
State1: The state with a note
note right of State1
Important information! You can write
notes.
end note
State1 --> State2
note left of State2 : This is the note to the left.
```
## Concurrency
As in plantUml you can specify concurrency using the -- symbol.
> ## Please edit the corresponding file in [/packages/mermaid/src/docs/syntax/timeline.md](../../packages/mermaid/src/docs/syntax/timeline.md).
# Timeline Diagram
> Timeline: This is an experimental diagram for now. The syntax and properties can change in future releases. The syntax is stable except for the icon integration which is the experimental part.
"A timeline is a type of diagram used to illustrate a chronology of events, dates, or periods of time. It is usually presented graphically to indicate the passing of time, and it is usually organized chronologically. A basic timeline presents a list of events in chronological order, usually using dates as markers. A timeline can also be used to show the relationship between events, such as the relationship between the events of a person's life" [(Wikipedia)](https://en.wikipedia.org/wiki/Timeline).
### An example of a timeline
```mermaid-example
timeline
title History of Social Media Platform
2002 : LinkedIn
2004 : Facebook
: Google
2005 : YouTube
2006 : Twitter
```
```mermaid
timeline
title History of Social Media Platform
2002 : LinkedIn
2004 : Facebook
: Google
2005 : YouTube
2006 : Twitter
```
## Syntax
The syntax for creating Timeline diagram is simple. You always start with the `timeline` keyword to let mermaid know that you want to create a timeline diagram.
After that there is a possibility to add a title to the timeline. This is done by adding a line with the keyword `title` followed by the title text.
Then you add the timeline data, where you always start with a time period, followed by a colon and then the text for the event. Optionally you can add a second colon and then the text for the event. So, you can have one or more events per time period.
```json
{time period} : {event}
```
or
```json
{time period} : {event} : {event}
```
or
```json
{time period} : {event}
: {event}
: {event}
```
**NOTE**: Both time period and event are simple text, and not limited to numbers.
Let us look at the syntax for the example above.
```mermaid-example
timeline
title History of Social Media Platform
2002 : LinkedIn
2004 : Facebook : Google
2005 : YouTube
2006 : Twitter
```
```mermaid
timeline
title History of Social Media Platform
2002 : LinkedIn
2004 : Facebook : Google
2005 : YouTube
2006 : Twitter
```
In this way we can use a text outline to generate a timeline diagram.
The sequence of time period and events is important, as it will be used to draw the timeline. The first time period will be placed at the left side of the timeline, and the last time period will be placed at the right side of the timeline.
Similarly, the first event will be placed at the top for that specific time period, and the last event will be placed at the bottom.
## Grouping of time periods in sections/ages
You can group time periods in sections/ages. This is done by adding a line with the keyword `section` followed by the section name.
All subsequent time periods will be placed in this section until a new section is defined.
If no section is defined, all time periods will be placed in the default section.
Let us look at an example, where we have grouped the time periods in sections.
```mermaid-example
timeline
title Timeline of Industrial Revolution
section 17th-20th century
Industry 1.0 : Machinery, Water power, Steam <br>power
Industry 2.0 : Electricity, Internal combustion engine, Mass production
Industry 3.0 : Electronics, Computers, Automation
section 21st century
Industry 4.0 : Internet, Robotics, Internet of Things
Industry 5.0 : Artificial intelligence, Big data, 3D printing
```
```mermaid
timeline
title Timeline of Industrial Revolution
section 17th-20th century
Industry 1.0 : Machinery, Water power, Steam <br>power
Industry 2.0 : Electricity, Internal combustion engine, Mass production
Industry 3.0 : Electronics, Computers, Automation
section 21st century
Industry 4.0 : Internet, Robotics, Internet of Things
Industry 5.0 : Artificial intelligence, Big data, 3D printing
```
As you can see, the time periods are placed in the sections, and the sections are placed in the order they are defined.
All time periods and events under a given section follow a similar color scheme. This is done to make it easier to see the relationship between time periods and events.
## Wrapping of text for long time-periods or events
By default, the text for time-periods and events will be wrapped if it is too long. This is done to avoid that the text is drawn outside the diagram.
You can also use `<br>` to force a line break.
Let us look at another example, where we have a long time period, and a long event.
```mermaid-example
timeline
title England's History Timeline
section Stone Age
7600 BC : Britain's oldest known house was built in Orkney, Scotland
6000 BC : Sea levels rise and Britain becomes an island.<br> The people who live here are hunter-gatherers.
section Bronze Age
2300 BC : People arrive from Europe and settle in Britain. <br>They bring farming and metalworking.
: New styles of pottery and ways of burying the dead appear.
2200 BC : The last major building works are completed at Stonehenge.<br> People now bury their dead in stone circles.
: The first metal objects are made in Britain.Some other nice things happen. it is a good time to be alive.
```
```mermaid
timeline
title England's History Timeline
section Stone Age
7600 BC : Britain's oldest known house was built in Orkney, Scotland
6000 BC : Sea levels rise and Britain becomes an island.<br> The people who live here are hunter-gatherers.
section Bronze Age
2300 BC : People arrive from Europe and settle in Britain. <br>They bring farming and metalworking.
: New styles of pottery and ways of burying the dead appear.
2200 BC : The last major building works are completed at Stonehenge.<br> People now bury their dead in stone circles.
: The first metal objects are made in Britain.Some other nice things happen. it is a good time to be alive.
```
```mermaid-example
timeline
title MermaidChart 2023 Timeline
section 2023 Q1 <br> Release Personal Tier
Bullet 1 : sub-point 1a : sub-point 1b
: sub-point 1c
Bullet 2 : sub-point 2a : sub-point 2b
section 2023 Q2 <br> Release XYZ Tier
Bullet 3 : sub-point <br> 3a : sub-point 3b
: sub-point 3c
Bullet 4 : sub-point 4a : sub-point 4b
```
```mermaid
timeline
title MermaidChart 2023 Timeline
section 2023 Q1 <br> Release Personal Tier
Bullet 1 : sub-point 1a : sub-point 1b
: sub-point 1c
Bullet 2 : sub-point 2a : sub-point 2b
section 2023 Q2 <br> Release XYZ Tier
Bullet 3 : sub-point <br> 3a : sub-point 3b
: sub-point 3c
Bullet 4 : sub-point 4a : sub-point 4b
```
## Styling of time periods and events
As explained earlier, each section has a color scheme, and each time period and event under a section follow the similar color scheme.
However, if there is no section defined, then we have two possibilities:
1. Style time periods individually, i.e. each time period(and its corresponding events) will have its own color scheme. This is the DEFAULT behavior.
```mermaid-example
timeline
title History of Social Media Platform
2002 : LinkedIn
2004 : Facebook : Google
2005 : YouTube
2006 : Twitter
```
```mermaid
timeline
title History of Social Media Platform
2002 : LinkedIn
2004 : Facebook : Google
2005 : YouTube
2006 : Twitter
```
**NOTE**: that there are no sections defined, and each time period and its corresponding events will have its own color scheme.
2. Disable the multiColor option using the `disableMultiColor` option. This will make all time periods and events follow the same color scheme.
You will need to add this option either via mermaid.initialize function or directives.
```javascript
mermaid.initialize({
theme: 'base',
startOnLoad: true,
logLevel: 0,
timeline: {
disableMulticolor: false,
},
...
...
```
let us look at same example, where we have disabled the multiColor option.
```mermaid-example
---
config:
logLevel: 'debug'
theme: 'base'
timeline:
disableMulticolor: true
---
timeline
title History of Social Media Platform
2002 : LinkedIn
2004 : Facebook : Google
2005 : YouTube
2006 : Twitter
```
```mermaid
---
config:
logLevel: 'debug'
theme: 'base'
timeline:
disableMulticolor: true
---
timeline
title History of Social Media Platform
2002 : LinkedIn
2004 : Facebook : Google
2005 : YouTube
2006 : Twitter
```
### Customizing Color scheme
You can customize the color scheme using the `cScale0` to `cScale11` theme variables, which will change the background colors. Mermaid allows you to set unique colors for up-to 12 sections, where `cScale0` variable will drive the value of the first section or time-period, `cScale1` will drive the value of the second section and so on.
In case you have more than 12 sections, the color scheme will start to repeat.
If you also want to change the foreground color of a section, you can do so use theme variables corresponding `cScaleLabel0` to `cScaleLabel11` variables.
**NOTE**: Default values for these theme variables are picked from the selected theme. If you want to override the default values, you can use the `initialize` call to add your custom theme variable values.
Example:
Now let's override the default values for the `cScale0` to `cScale2` variables:
```mermaid-example
---
config:
logLevel: 'debug'
theme: 'default'
themeVariables:
cScale0: '#ff0000'
cScaleLabel0: '#ffffff'
cScale1: '#00ff00'
cScale2: '#0000ff'
cScaleLabel2: '#ffffff'
---
timeline
title History of Social Media Platform
2002 : LinkedIn
2004 : Facebook : Google
2005 : YouTube
2006 : Twitter
2007 : Tumblr
2008 : Instagram
2010 : Pinterest
```
```mermaid
---
config:
logLevel: 'debug'
theme: 'default'
themeVariables:
cScale0: '#ff0000'
cScaleLabel0: '#ffffff'
cScale1: '#00ff00'
cScale2: '#0000ff'
cScaleLabel2: '#ffffff'
---
timeline
title History of Social Media Platform
2002 : LinkedIn
2004 : Facebook : Google
2005 : YouTube
2006 : Twitter
2007 : Tumblr
2008 : Instagram
2010 : Pinterest
```
See how the colors are changed to the values specified in the theme variables.
## Themes
Mermaid supports a bunch of pre-defined themes which you can use to find the right one for you. PS: you can actually override an existing theme's variable to get your own custom theme going. Learn more about [theming your diagram](../config/theming.md).
The following are the different pre-defined theme options:
- `base`
- `forest`
- `dark`
- `default`
- `neutral`
**NOTE**: To change theme you can either use the `initialize` call or _directives_. Learn more about [directives](../config/directives.md)
Let's put them to use, and see how our sample diagram looks in different themes:
### Base Theme
```mermaid-example
---
config:
logLevel: 'debug'
theme: 'base'
---
timeline
title History of Social Media Platform
2002 : LinkedIn
2004 : Facebook : Google
2005 : YouTube
2006 : Twitter
2007 : Tumblr
2008 : Instagram
2010 : Pinterest
```
```mermaid
---
config:
logLevel: 'debug'
theme: 'base'
---
timeline
title History of Social Media Platform
2002 : LinkedIn
2004 : Facebook : Google
2005 : YouTube
2006 : Twitter
2007 : Tumblr
2008 : Instagram
2010 : Pinterest
```
### Forest Theme
```mermaid-example
---
config:
logLevel: 'debug'
theme: 'forest'
---
timeline
title History of Social Media Platform
2002 : LinkedIn
2004 : Facebook : Google
2005 : YouTube
2006 : Twitter
2007 : Tumblr
2008 : Instagram
2010 : Pinterest
```
```mermaid
---
config:
logLevel: 'debug'
theme: 'forest'
---
timeline
title History of Social Media Platform
2002 : LinkedIn
2004 : Facebook : Google
2005 : YouTube
2006 : Twitter
2007 : Tumblr
2008 : Instagram
2010 : Pinterest
```
### Dark Theme
```mermaid-example
---
config:
logLevel: 'debug'
theme: 'dark'
---
timeline
title History of Social Media Platform
2002 : LinkedIn
2004 : Facebook : Google
2005 : YouTube
2006 : Twitter
2007 : Tumblr
2008 : Instagram
2010 : Pinterest
```
```mermaid
---
config:
logLevel: 'debug'
theme: 'dark'
---
timeline
title History of Social Media Platform
2002 : LinkedIn
2004 : Facebook : Google
2005 : YouTube
2006 : Twitter
2007 : Tumblr
2008 : Instagram
2010 : Pinterest
```
### Default Theme
```mermaid-example
---
config:
logLevel: 'debug'
theme: 'default'
---
timeline
title History of Social Media Platform
2002 : LinkedIn
2004 : Facebook : Google
2005 : YouTube
2006 : Twitter
2007 : Tumblr
2008 : Instagram
2010 : Pinterest
```
```mermaid
---
config:
logLevel: 'debug'
theme: 'default'
---
timeline
title History of Social Media Platform
2002 : LinkedIn
2004 : Facebook : Google
2005 : YouTube
2006 : Twitter
2007 : Tumblr
2008 : Instagram
2010 : Pinterest
```
### Neutral Theme
```mermaid-example
---
config:
logLevel: 'debug'
theme: 'neutral'
---
timeline
title History of Social Media Platform
2002 : LinkedIn
2004 : Facebook : Google
2005 : YouTube
2006 : Twitter
2007 : Tumblr
2008 : Instagram
2010 : Pinterest
```
```mermaid
---
config:
logLevel: 'debug'
theme: 'neutral'
---
timeline
title History of Social Media Platform
2002 : LinkedIn
2004 : Facebook : Google
2005 : YouTube
2006 : Twitter
2007 : Tumblr
2008 : Instagram
2010 : Pinterest
```
## Integrating with your library/website
Timeline uses experimental lazy loading & async rendering features which could change in the future.The lazy loading is important in order to be able to add additional diagrams going forward.
You can use this method to add mermaid including the timeline diagram to a web page:
```html
<script type="module">
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs';
</script>
```
You can also refer the [implementation in the live editor](https://github.com/mermaid-js/mermaid-live-editor/blob/develop/src/lib/util/mermaid.ts) to see how the async loading is done.
> ## Please edit the corresponding file in [/packages/mermaid/src/docs/syntax/treemap.md](../../packages/mermaid/src/docs/syntax/treemap.md).
# Treemap Diagram
> A treemap diagram displays hierarchical data as a set of nested rectangles. Each branch of the tree is represented by a rectangle, which is then tiled with smaller rectangles representing sub-branches.
> **Warning**
> This is a new diagram type in Mermaid. Its syntax may evolve in future versions.
## Introduction
Treemap diagrams are an effective way to visualize hierarchical data and show proportions between categories and subcategories. The size of each rectangle is proportional to the value it represents, making it easy to compare different parts of a hierarchy.
Treemap diagrams are particularly useful for:
- Visualizing hierarchical data structures
- Comparing proportions between categories
- Displaying large amounts of hierarchical data in a limited space
- Identifying patterns and outliers in hierarchical data
## Syntax
```
treemap-beta
"Section 1"
"Leaf 1.1": 12
"Section 1.2"
"Leaf 1.2.1": 12
"Section 2"
"Leaf 2.1": 20
"Leaf 2.2": 25
```
### Node Definition
Nodes in a treemap are defined using the following syntax:
- **Section/Parent nodes**: Defined with quoted text `"Section Name"`
- **Leaf nodes with values**: Defined with quoted text followed by a colon and value `"Leaf Name": value`
- **Hierarchy**: Created using indentation (spaces or tabs)
- **Styling**: Nodes can be styled using the `:::class` syntax
| useMaxWidth | When true, the diagram width is set to 100% and scales with available space | true |
| padding | Internal padding between nodes | 10 |
| diagramPadding | Padding around the entire diagram | 8 |
| showValues | Whether to show values in the treemap | true |
| nodeWidth | Width of nodes | 100 |
| nodeHeight | Height of nodes | 40 |
| borderWidth | Width of borders | 1 |
| valueFontSize | Font size for values | 12 |
| labelFontSize | Font size for labels | 14 |
| valueFormat | Format for values (see Value Formatting section) | ',' |
## Advanced Features
### Value Formatting
Values in treemap diagrams can be formatted to display in different ways using the `valueFormat` configuration option. This option primarily uses [D3's format specifiers](https://github.com/d3/d3-format#locale_format) to control how numbers are displayed, with some additional special cases for common formats.
Some common format patterns:
- `,` - Thousands separator (default)
- `$` - Add dollar sign
- `.1f` - Show one decimal place
- `.1%` - Show as percentage with one decimal place
- `$0,0` - Dollar sign with thousands separator
- `$.2f` - Dollar sign with 2 decimal places
- `$,.2f` - Dollar sign with thousands separator and 2 decimal places
The treemap diagram supports both standard D3 format specifiers and some common currency formats that combine the dollar sign with other formatting options.
2. **File System Analysis**: Showing disk space usage by folders and files
3. **Population Demographics**: Displaying population distribution across regions and subregions
4. **Product Hierarchies**: Visualizing product categories and their sales volumes
5. **Organizational Structures**: Representing departments and team sizes in a company
## Limitations
- Treemap diagrams work best when the data has a natural hierarchy
- Very small values may be difficult to see or label in a treemap diagram
- Deep hierarchies (many levels) can be challenging to represent clearly
- Treemap diagrams are not well suited for representing data with negative values
## Related Diagrams
If treemap diagrams don't suit your needs, consider these alternatives:
- [**Pie Charts**](./pie.md): For simple proportion comparisons without hierarchy
- **Sunburst Diagrams**: For hierarchical data with a radial layout (yet to be released in Mermaid).
- [**Sankey Diagrams**](./sankey.md): For flow-based hierarchical data
## Notes
The treemap diagram implementation in Mermaid is designed to be simple to use while providing powerful visualization capabilities. As this is a newer diagram type, feedback and feature requests are welcome through the Mermaid GitHub repository.
> ## Please edit the corresponding file in [/packages/mermaid/src/docs/syntax/userJourney.md](../../packages/mermaid/src/docs/syntax/userJourney.md).
# User Journey Diagram
> User journeys describe at a high level of detail exactly what steps different users take to complete a specific task within a system, application or website. This technique shows the current (as-is) user workflow, and reveals areas of improvement for the to-be workflow. (Wikipedia)
Mermaid can render user journey diagrams:
```mermaid-example
journey
title My working day
section Go to work
Make tea: 5: Me
Go upstairs: 3: Me
Do work: 1: Me, Cat
section Go home
Go downstairs: 5: Me
Sit down: 5: Me
```
```mermaid
journey
title My working day
section Go to work
Make tea: 5: Me
Go upstairs: 3: Me
Do work: 1: Me, Cat
section Go home
Go downstairs: 5: Me
Sit down: 5: Me
```
Each user journey is split into sections, these describe the part of the task
the user is trying to complete.
Tasks syntax is `Task name: <score>: <comma separated list of actors>`
> ## Please edit the corresponding file in [/packages/mermaid/src/docs/syntax/xyChart.md](../../packages/mermaid/src/docs/syntax/xyChart.md).
# XY Chart
> In the context of mermaid-js, the XY chart is a comprehensive charting module that encompasses various types of charts that utilize both x-axis and y-axis for data representation. Presently, it includes two fundamental chart types: the bar chart and the line chart. These charts are designed to visually display and analyze data that involve two numerical variables.
> It's important to note that while the current implementation of mermaid-js includes these two chart types, the framework is designed to be dynamic and adaptable. Therefore, it has the capacity for expansion and the inclusion of additional chart types in the future. This means that users can expect an evolving suite of charting options within the XY chart module, catering to various data visualization needs as new chart types are introduced over time.
## Example
```mermaid-example
xychart
title "Sales Revenue"
x-axis [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
> All text values that contain only one word can be written without `"`. If a text value has many words in it, specifically if it contains spaces, enclose the value in `"`
### Orientations
The chart can be drawn horizontal or vertical, default value is vertical.
```
xychart horizontal
...
```
### Title
The title is a short description of the chart and it will always render on top of the chart.
#### Example
```
xychart
title "This is a simple example"
...
```
> **Note**
> If the title is a single word one no need to use `"`, but if it has space `"` is needed
### x-axis
The x-axis primarily serves as a categorical value, although it can also function as a numeric range value when needed.
#### Example
1. `x-axis title min --> max` x-axis will function as numeric with the given range
2. `x-axis "title with space" [cat1, "cat2 with space", cat3]` x-axis if categorical, categories are text type
### y-axis
The y-axis is employed to represent numerical range values, it cannot have categorical values.
#### Example
1. `y-axis title min --> max`
2. `y-axis title` it will only add the title, the range will be auto generated from data.
> **Note**
> Both x and y axis are optional if not provided we will try to create the range
### Line chart
A line chart offers the capability to graphically depict lines.
#### Example
1. `line [2.3, 45, .98, -3.4]` it can have all valid numeric values.
### Bar chart
A bar chart offers the capability to graphically depict bars.
#### Example
1. `bar [2.3, 45, .98, -3.4]` it can have all valid numeric values.
#### Simplest example
The only two things required are the chart name (`xychart`) and one data set. So you will be able to draw a chart with a simple config like
| backgroundColor | Background color of the whole chart |
| titleColor | Color of the Title text |
| xAxisLabelColor | Color of the x-axis labels |
| xAxisTitleColor | Color of the x-axis title |
| xAxisTickColor | Color of the x-axis tick |
| xAxisLineColor | Color of the x-axis line |
| yAxisLabelColor | Color of the y-axis labels |
| yAxisTitleColor | Color of the y-axis title |
| yAxisTickColor | Color of the y-axis tick |
| yAxisLineColor | Color of the y-axis line |
| plotColorPalette | String of colors separated by comma e.g. "#f3456, #43445" |
### Setting Colors for Lines and Bars
To set the color for lines and bars, use the `plotColorPalette` parameter. Colors in the palette will correspond sequentially to the elements in your chart (e.g., first bar/line will use the first color specified in the palette).
> ## Please edit the corresponding file in [/packages/mermaid/src/docs/syntax/zenuml.md](../../packages/mermaid/src/docs/syntax/zenuml.md).
# ZenUML
> A Sequence diagram is an interaction diagram that shows how processes operate with one another and in what order.
Mermaid can render sequence diagrams with [ZenUML](https://zenuml.com). Note that ZenUML uses a different
syntax than the original Sequence Diagram in mermaid.
```mermaid-example
zenuml
title Demo
Alice->John: Hello John, how are you?
John->Alice: Great!
Alice->John: See you later!
```
```mermaid
zenuml
title Demo
Alice->John: Hello John, how are you?
John->Alice: Great!
Alice->John: See you later!
```
## Syntax
### Participants
The participants can be defined implicitly as in the first example on this page. The participants or actors are
rendered in order of appearance in the diagram source text. Sometimes you might want to show the participants in a
different order than how they appear in the first message. It is possible to specify the actor's order of
appearance by doing the following:
```mermaid-example
zenuml
title Declare participant (optional)
Bob
Alice
Alice->Bob: Hi Bob
Bob->Alice: Hi Alice
```
```mermaid
zenuml
title Declare participant (optional)
Bob
Alice
Alice->Bob: Hi Bob
Bob->Alice: Hi Alice
```
### Annotators
If you specifically want to use symbols instead of just rectangles with text you can do so by using the annotator syntax to declare participants as per below.
```mermaid-example
zenuml
title Annotators
@Actor Alice
@Database Bob
Alice->Bob: Hi Bob
Bob->Alice: Hi Alice
```
```mermaid
zenuml
title Annotators
@Actor Alice
@Database Bob
Alice->Bob: Hi Bob
Bob->Alice: Hi Alice
```
Here are the available annotators:

### Aliases
The participants can have a convenient identifier and a descriptive label.
```mermaid-example
zenuml
title Aliases
A as Alice
J as John
A->J: Hello John, how are you?
J->A: Great!
```
```mermaid
zenuml
title Aliases
A as Alice
J as John
A->J: Hello John, how are you?
J->A: Great!
```
## Messages
Messages can be one of:
1. Sync message
2. Async message
3. Creation message
4. Reply message
### Sync message
You can think of a sync (blocking) method in a programming language.
```mermaid-example
zenuml
title Sync message
A.SyncMessage
A.SyncMessage(with, parameters) {
B.nestedSyncMessage()
}
```
```mermaid
zenuml
title Sync message
A.SyncMessage
A.SyncMessage(with, parameters) {
B.nestedSyncMessage()
}
```
### Async message
You can think of an async (non-blocking) method in a programming language.
Fire an event and forget about it.
```mermaid-example
zenuml
title Async message
Alice->Bob: How are you?
```
```mermaid
zenuml
title Async message
Alice->Bob: How are you?
```
### Creation message
We use `new` keyword to create an object.
```mermaid-example
zenuml
new A1
new A2(with, parameters)
```
```mermaid
zenuml
new A1
new A2(with, parameters)
```
### Reply message
There are three ways to express a reply message:
```mermaid-example
zenuml
// 1. assign a variable from a sync message.
a = A.SyncMessage()
// 1.1. optionally give the variable a type
SomeType a = A.SyncMessage()
// 2. use return keyword
A.SyncMessage() {
return result
}
// 3. use @return or @reply annotator on an async message
@return
A->B: result
```
```mermaid
zenuml
// 1. assign a variable from a sync message.
a = A.SyncMessage()
// 1.1. optionally give the variable a type
SomeType a = A.SyncMessage()
// 2. use return keyword
A.SyncMessage() {
return result
}
// 3. use @return or @reply annotator on an async message
@return
A->B: result
```
The third way `@return` is rarely used, but it is useful when you want to return to one level up.
```mermaid-example
zenuml
title Reply message
Client->A.method() {
B.method() {
if(condition) {
return x1
// return early
@return
A->Client: x11
}
}
return x2
}
```
```mermaid
zenuml
title Reply message
Client->A.method() {
B.method() {
if(condition) {
return x1
// return early
@return
A->Client: x11
}
}
return x2
}
```
## Nesting
Sync messages and Creation messages are naturally nestable with `{}`.
```mermaid-example
zenuml
A.method() {
B.nested_sync_method()
B->C: nested async message
}
```
```mermaid
zenuml
A.method() {
B.nested_sync_method()
B->C: nested async message
}
```
## Comments
It is possible to add comments to a sequence diagram with `// comment` syntax.
Comments will be rendered above the messages or fragments. Comments on other places
are ignored. Markdown is supported.
See the example below:
```mermaid-example
zenuml
// a comment on a participant will not be rendered
BookService
// a comment on a message.
// **Markdown** is supported.
BookService.getBook()
```
```mermaid
zenuml
// a comment on a participant will not be rendered
BookService
// a comment on a message.
// **Markdown** is supported.
BookService.getBook()
```
## Loops
It is possible to express loops in a ZenUML diagram. This is done by any of the
following notations:
1. while
2. for
3. forEach, foreach
4. loop
```zenuml
while(condition) {
...statements...
}
```
See the example below:
```mermaid-example
zenuml
Alice->John: Hello John, how are you?
while(true) {
John->Alice: Great!
}
```
```mermaid
zenuml
Alice->John: Hello John, how are you?
while(true) {
John->Alice: Great!
}
```
## Alt
It is possible to express alternative paths in a sequence diagram. This is done by the notation
```zenuml
if(condition1) {
...statements...
} else if(condition2) {
...statements...
} else {
...statements...
}
```
See the example below:
```mermaid-example
zenuml
Alice->Bob: Hello Bob, how are you?
if(is_sick) {
Bob->Alice: Not so good :(
} else {
Bob->Alice: Feeling fresh like a daisy
}
```
```mermaid
zenuml
Alice->Bob: Hello Bob, how are you?
if(is_sick) {
Bob->Alice: Not so good :(
} else {
Bob->Alice: Feeling fresh like a daisy
}
```
## Opt
It is possible to render an `opt` fragment. This is done by the notation
```zenuml
opt {
...statements...
}
```
See the example below:
```mermaid-example
zenuml
Alice->Bob: Hello Bob, how are you?
Bob->Alice: Not so good :(
opt {
Bob->Alice: Thanks for asking
}
```
```mermaid
zenuml
Alice->Bob: Hello Bob, how are you?
Bob->Alice: Not so good :(
opt {
Bob->Alice: Thanks for asking
}
```
## Parallel
It is possible to show actions that are happening in parallel.
This is done by the notation
```zenuml
par {
statement1
statement2
statement3
}
```
See the example below:
```mermaid-example
zenuml
par {
Alice->Bob: Hello guys!
Alice->John: Hello guys!
}
```
```mermaid
zenuml
par {
Alice->Bob: Hello guys!
Alice->John: Hello guys!
}
```
## Try/Catch/Finally (Break)
It is possible to indicate a stop of the sequence within the flow (usually used to model exceptions).
This is done by the notation
```
try {
...statements...
} catch {
...statements...
} finally {
...statements...
}
```
See the example below:
```mermaid-example
zenuml
try {
Consumer->API: Book something
API->BookingService: Start booking process
} catch {
API->Consumer: show failure
} finally {
API->BookingService: rollback status
}
```
```mermaid
zenuml
try {
Consumer->API: Book something
API->BookingService: Start booking process
} catch {
API->Consumer: show failure
} finally {
API->BookingService: rollback status
}
```
## Integrating with your library/website.
Zenuml uses the experimental lazy loading & async rendering features which could change in the future.
You can use this method to add mermaid including the zenuml diagram to a web page:
```html
<script type="module">
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs';
import zenuml from 'https://cdn.jsdelivr.net/npm/@mermaid-js/mermaid-zenuml@0.1.0/dist/mermaid-zenuml.esm.min.mjs';
description: Анализ и оптимизация существующего бизнес-процесса — process discovery (реконструкция as-is процесса из кода Laravel и audit-логов), поиск узких мест, трассировка требование→процесс, метрики и KPI процесса. Триггеры — «проанализируй процесс», «где узкое место», «process discovery», «как устроен процесс X», «метрики процесса», «оптимизируй процесс». Раздел C10 карты «Бизнес-процессы (общее)».
4. **Update §0 «Сводка».** Increment счётчик ⏸ для соответствующего prefix. Шапка `## 0` содержит таблицу типа `Биз 24 ✅ / 7 ⏸` — bump до `8 ⏸`. **Также** «Итого X / Y ✅ / Z ⏸» — bump соответствующие.
5. **Bump versions.** Header (`v1.83 от 13.05.2026 (day +1)` → `v1.84 от 13.05.2026 (day +1)`), footer (last line same), добавить запись в `## 9. История версий`.
6. **Sync CLAUDE.md.**В`CLAUDE.md` §0 row «Открытые вопросы» bump `v1.83+` → `v1.84+`. Помним: CLAUDE.md правится ТОЛЬКО через `/claude-md-management:revise-claude-md` (§5 п.10) — финальный шаг делегируем заказчику или этому skill'у через sub-invocation.
For reviewing a diff, branch, or PR with DB changes - use the rls-reviewer agent.
disable-model-invocation: true
---
# RLS-check — verify RLS на таблице
## Когда использовать
При добавлении или модификации таблицы в `db/schema.sql`, особенно перед коммитом. Инкапсулирует 7-item checklist; lefthook pre-commit job 7 (squawk) ловит только часть.
Invoke via `/rls-check <table_name>`.
## Граница с агентом rls-reviewer
`rls-check` (этот скил) и `rls-reviewer` (агент, `.claude/agents/rls-reviewer.md`)
оба проверяют RLS, но в разных ситуациях. Правило выбора:
- Знаешь имя одной конкретной таблицы, проверка вручную перед коммитом →
**`/rls-check <table>`** (этот скил).
- Есть diff / ветка / PR с изменениями БД, набор таблиц заранее не известен →
**агент `rls-reviewer`**.
Скил работает в основном контексте по одной названной таблице и прогоняет
**8 строк вывода** — 7 статических пунктов + живой дымовой тест
(`pest --filter RlsSmokeTest`, шаг 7). Агент работает в отдельном контексте
субагента, разбирает diff/миграцию/PR и прогоняет только **7 статических**
строк — дымовой тест намеренно не запускает.
Первые 7 строк вывода у обоих — общее статическое ядро (tenant_id, ENABLE RLS,
SELECT/ALL политики, GRANT'ы 5 ролей, CHANGELOG, squawk). Это не дублирование:
ядро проверок одно, сценарии вызова разные. Дымовой тест — только в скиле:
запуск Pest в ревью-субагенте медленный и задевает гонки `--parallel`
(квирки 72/77, см. `.claude/agents/pest-parallel-debugger.md`).
## Checklist
1. **tenant_id column.** Grep `db/schema.sql` для `CREATE TABLE <name>`. Verify:
- `tenant_id UUID NOT NULL REFERENCES tenants(id)` присутствует, **OR**
- SaaS-level exemption — explicit comment типа `-- SaaS-level: no tenant_id (justification)`.
4. **Role GRANTs.**В`db/02_grants.sql` должны быть GRANT'ы для 5 ролей. Проверить по pattern existing tables.
```bash
grep -E "GRANT.*ON\s+<name>" db/02_grants.sql
```
Expected: ≥5 GRANT statements (по одному на роль) или group GRANT.
5. **CHANGELOG entry.**В`db/CHANGELOG_schema.md` должна быть запись с датой + table name + summary (CLAUDE.md §5 п.8).
```bash
grep "<name>" db/CHANGELOG_schema.md
```
6. **squawk lint.**
```bash
./bin/squawk.exe db/schema.sql 2>&1 | tail -10
```
Expected: exit 0, no issues.
7. **Smoke test.**`tests/Feature/RlsSmokeTest.php` (или новый тест для конкретной таблицы) должен assert'ить, что user в tenant A не видит row из tenant B для новой таблицы.
```bash
cd app && ./vendor/bin/pest --filter RlsSmokeTest 2>&1 | tail -10
```
Expected: all assertions pass.
## Output
Print результат per item + total:
```text
RLS-check: <table_name>
[✅] tenant_id column
[✅] ENABLE RLS
[✅] SELECT policy
[✅] ALL policy
[✅] 5-role GRANTs
[✅] CHANGELOG entry
[✅] squawk passes
[✅] smoke test passes
Pass: 8/8
```
Or failure listing: `[❌] tenant_id column missing — db/schema.sql:NNNN`.
## Не использовать когда
- Modifying existing well-RLS'd table без новых columns — overhead.
description: Project-local wrapper для superpowers:subagent-driven-development — добавляет обязательный git-safety verify-протокол per Pravila §15.1. Использовать вместо marketplace-варианта при работе с git-коммит-задачами в субагентах.
---
# Subagent-Driven Development (project wrapper)
Этот скил — проектная обёртка над marketplace-скилом `superpowers:subagent-driven-development`. Дополняет его обязательным git-safety verify-протоколом per Pravila §15.1.
## Когда использовать
Когда нужно делегировать задачу субагенту через Task tool — особенно git-коммит-задачи (Sprint 6 прецедент: Haiku-субагенты угнали ветку параллельной сессии).
## Что делать
1. **Откройте marketplace-скил**`superpowers:subagent-driven-development` для общего workflow (fresh subagent per task + two-stage review).
2. **Перед каждой Task-инвокацией** прочитайте и выполните pre-spawn-чеклист — [references/git-safety-checklist.md](references/git-safety-checklist.md) §A.
3. **После каждой Task-инвокации** прочитайте и выполните post-subagent-чеклист — там же §B.
4. **Hard-rule §15.1** — git-коммит-задача = модель Sonnet/Opus, никогда Haiku. Read-only git-операции (`log`, `status`, `diff`, `rev-parse`, `branch --show-current`, `worktree list`) разрешены любой модели.
Хук `tools/subagent-prompt-prefix.mjs` (зарегистрирован в `.claude/settings.json`) автоматически инжектит git-safety заголовок в каждый Task-prompt — это **первая** линия защиты. Чеклист из этого скила — **вторая** линия (защита со стороны контроллера).
- HEAD двинулся, но субагент в отчёте об этом не упомянул;
- в diff'е есть файлы вне scope задачи.
## §D. Обязательный формат отчёта субагента
Субагент в конце ответа выписывает блок:
```
=== GIT REPORT ===
cwd: <pwd>
branch: <git branch --show-current>
HEAD: <git rev-parse HEAD>
HEAD^: <git rev-parse HEAD^>
status: <git status --short>
=== END GIT REPORT ===
```
Отсутствие блока = контроллер считает результат недостоверным и запускает §B-чеклист сам через Bash.
## §E. Соотношение с code-review
Двухстадийное review (Pravila §4.5 / PSR_v1 R10) сохраняется. Git-safety-чеклист **не заменяет** code-review — он стоит **до** него (нет смысла ревьюить diff, если он не в той ветке).
"comment":"Фаза 0 #3 — официальный hosted GitHub MCP (https://github.com/github/github-mcp-server). Требует env GITHUB_TOKEN с PAT (scopes: repo, read:org, не давать admin/delete). Раньше использовали deprecated @modelcontextprotocol/server-github — заменён 06.05.2026."
"comment":"Фаза 0 #3 — официальный hosted GitHub MCP (https://github.com/github/github-mcp-server). Требует env GITHUB_TOKEN с PAT (scopes: repo, read:org, не давать admin/delete). Раньше использовали deprecated @modelcontextprotocol/server-github — заменён 06.05.2026. X-MCP-Toolsets явно перечисляет toolset'ы, включая `projects` (GitHub Projects v2 — доски/спринты/milestones) для раздела C9 «Управление проектами» — план docs/superpowers/plans/2026-05-17-c9-project-management-tooling-integration.md (GH1). Заголовок заменяет default-набор: список явный, чтобы не сузить поверхность."
},
"laravel-boost":{
"command":"php",
@@ -23,6 +24,35 @@
"command":"npx",
"args":["-y","semgrep-mcp"],
"comment":"Фаза 3 #25 — Semgrep MCP (SAST). Семантический поиск/анализ кода через Semgrep rules в Claude Code. Пакет: npmjs.com/package/semgrep-mcp — если 404, запустить 'npm search semgrep mcp' для актуального имени."
},
"sentry":{
"command":"npx",
"args":["-y","@sentry/mcp-server"],
"env":{
"SENTRY_URL":"${SENTRY_URL}",
"SENTRY_AUTH_TOKEN":"${SENTRY_AUTH_TOKEN}"
},
"comment":"Off-phase tool — Sentry MCP для self-hosted экземпляра в Yandex Cloud (CLAUDE.md §2). Pending формализация в Tooling §3.3 #34 — sync нормативки отдельным планом. Package: @sentry/mcp-server@0.33.0+ (official sentry-bot, repo getsentry/sentry-mcp, bin sentry-mcp). Env vars: SENTRY_URL (https://sentry.<your-domain>.ru), SENTRY_AUTH_TOKEN (PAT scope: sentry:read). Credentials в .env.local (gitignored), Claude Code считывает env из shell startup. Если env пустые — MCP server fail gracefully."
"comment":"Off-phase tool — Redis MCP для Memurai (Windows service, Redis 7-совместимый, localhost:6379). Pending формализация в Tooling §3.3 #35 — sync нормативки отдельным планом. Package: @modelcontextprotocol/server-redis@2025.4.25 — DEPRECATED по статусу npm («Package no longer supported»), но Anthropic source, простой протокол, рабочий. Post-MVP migration на community alternative (e.g., @easy-mcps/redis-mcp-server@1.0.8 или @wenit/redis-mcp-server@1.0.3) когда подтвердим trust. READ-ONLY use — отладка очередей, кэша, Pest --parallel race (memory quirk 72). НЕ для prod (нет prod). Если в будущем prod Redis с auth — отдельный entry redis-prod с url через env var."
},
"_ruflo_isolated_note":"ruflo MCP-сервер отключён 18.05.2026 (заказчик: «изолируй, не удаляй»). Чтобы вернуть — восстановить блок 'ruflo': { command: 'npx', args: ['-y','ruflo@latest','mcp','start'], comment: ... }. См. memory feedback_ruflo_isolated.md, Tooling §4.10, CLAUDE.md §3.5.",
"universal-icons":{
"command":"npx",
"args":["-y","mcp-universal-icons"],
"comment":"Off-phase A4 design-tooling #45 — Universal Icons MCP (npm mcp-universal-icons, awssat, MIT). Поиск/вставка SVG-иконок из 10 коллекций, включая Lucide (проектный icon-set, CTO-19). Tools: search_icons / get_icon / health_check. SVG framework-neutral по умолчанию — НЕ запрашивать jsx/Tailwind-формат (PSR_v1 R6.0). Формализация — Tooling §4.20. ADR-006 граница UI2: иконки UI; бренд-логотипы — за 21st logo_search. План docs/superpowers/plans/2026-05-17-a4-design-tooling-integration.md."
},
"openapi":{
"command":"npx",
"args":["-y","@ivotoby/openapi-mcp-server"],
"env":{
"API_BASE_URL":"http://localhost",
"OPENAPI_SPEC_PATH":"./docs/api/openapi.yaml"
},
"comment":"A3 integration-tooling #47 — OpenAPI MCP (ivo-toby/mcp-openapi-server, @ivotoby/openapi-mcp-server v1.14.0, MIT). Exposes Лидерра REST API endpoints (docs/api/openapi.yaml) as MCP tools. Config via env-vars API_BASE_URL + OPENAPI_SPEC_PATH (stdio transport default). READ scope: API discovery/introspection for Claude Code. Формализован в Tooling §4.22, PSR_v1 R10.1 блок 3, Pravila §13.2."
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.