A repeatable flow to generate per-partner Tesztelési jegyzőkönyv (test report) .docx documents for FaceKom releases, against a new standard template. This is the producing companion to youtrack-tesztjegyzokonyv-attachment-recipe (which covers finding/downloading existing ones in YouTrack). Built 2026-06-26.

For Agents

  • Tool: a /fk-tjk Claude command + a stdlib Python docx renderer, both under /Users/levander/coding/facekom/.claude/. Claude-driven (drafts content per release), not a config CLI.
  • Practice: every FaceKom release (1.9.11.NN) needs one TJK per AFFECTED partner (not all 39), attached to that partner’s YouTrack release ticket. The project shortName is usually ASS<PARTNER> / BUG<PARTNER> but VARIES — MicroSec = MF, DÁP = DAP/ASSDAP — so the partner map stores ytProject explicitly.
  • Core vs partner-specific: a shared core change reuses the same report text across partners (verified byte-identical body); a partner customization gets bespoke content.
  • Template: tesztjegyzokonyv_sablon.docx has 19 <…> placeholders, each intact in a single <w:t> run, all in word/document.xml → plain string substitution preserves all styling (no docxtemplater/pandoc needed).
  • v1 manual / out of scope: evidence/screenshots, final pass/fail underline, PDF export, and attaching to YouTrack. No YouTrack write-back.
  • Full design + fact-check log: /Users/levander/coding/facekom/docs/superpowers/specs/2026-06-26-teszt-jegyzokonyv-flow-design.md (§13 verification).

When you need this — the observed practice

Each FaceKom release 1.9.11.NN produces one Tesztelési jegyzőkönyv per affected partner — attached as a .docx/PDF to that partner’s release-tracking ticket (see youtrack-tesztjegyzokonyv-attachment-recipe for where these live and how to fetch past ones).

  • Not all 39 partners — only those a release touches. Raiffeisen produces one for nearly every release; others sporadically, when a change reaches them.
  • Project shortName varies. Usually ASS<PARTNER> (release) or BUG<PARTNER> (bug), but there are exceptions — MicroSec = MF, DÁP = DAP / ASSDAP. Never guess it; the partner map (partners.json) pins ytProject per partner. Cross-check against client-registry (YouTrack suffix ≠ repo name).
  • Core change → reuse the same text. For a shared core fix, the identical report body is reused across partners — verified: the Oracle-timezone reports on MKB ASSMKB-90 and BB ASSBB-82 have byte-identical extracted text (the two .docx differ only by a few bytes of zip metadata; the body doesn’t even name the partner). Only the attachment target differs. Partner-specific changes get tailored content.
  • Mechanical vs human. Metadata (partner, version, ticket, type, tester/reviewer, dates, description, environment) is derivable. Evidence (screenshots) and the final pass/fail verdict come from a real test run → stay human.

The standard template — tesztjegyzokonyv_sablon.docx

A simplified redesign (authored 2026-05-29) that replaces 3 inconsistent legacy formats (legacy 2022/2024 with TOC + numbered sections; an ad-hoc 2026.04 technical report). This new template is the standardization target. 416 KB; embeds Helvetica Neue + Noto Sans Symbols fonts and one image.

Why plain string substitution is safe here

The template has 19 <…>-style placeholders, and each one is intact inside a single <w:t xml:space="preserve"> run (no run-splitting). So substituting the literal placeholder string with the value preserves every bit of styling — no docxtemplater, no pandoc, no run-merging needed. All 19 placeholders live only in word/document.xml; the three header parts and customXML carry none, so the renderer edits only document.xml.

Placeholder groups (13 single-value + 2 summaries + 4 repeated test-case = 19):

GroupPlaceholders
Metadata<partner>, <youtrack ticket>, <release verzió>, <pl. bugfix, cr, stb.>
People / dates<tesztelő neve>, <tesztelés dátuma>, <ellenőrző neve>, <ellenőrzés dátuma>
Description<Rövid ismertetés>
Environment<teszteszköz>, <környezet>, <böngésző és verziója – ha releváns>, <sdk verzió – ha releváns>
Test case (repeatable block)<teszteset címe>, <teszteset leírása>, <elvárt működés leírása>, <képernyőképek, …>
Summaries<a tesztelés rövid, szöveges ismertetése> (tester), <a tesztelés eredményének rövid, szöveges összegzése> (reviewer)

The “1. teszteset” number and the Sikeres / sikertelen and igen / nem choices are literal text, not placeholders (the doc has no numPr / TOC). The renderer clones the test-case block and renumbers; the underline-the-correct-option choices stay manual.

What was built

Quick Reference — file paths (all under /Users/levander/coding/facekom/)

FileRole
.claude/commands/fk-tjk.mdThe /fk-tjk procedure (Claude-driven)
.claude/scripts/tjk/render_tjk.pyStdlib-only docx renderer + self-check + __main__ demo
.claude/scripts/tjk/partners.jsonPartner map: key → {display, ytProject, defaultEnv} (12 seeded)
.claude/scripts/tjk/tesztjegyzokonyv_sablon.docxPinned template (version-locked, never mutated)
.claude/scripts/tjk/tests/test_render.pyFixture-based render assertions
out/Generated per-partner .json + .docx (scratch)

The layout deliberately mirrors the existing /fk-ticket flow (command in .claude/commands/ + helper package in .claude/scripts/).

The command — .claude/commands/fk-tjk.md

The repeatable procedure Claude follows each release. Read-only context gathering, then draft, then render:

  1. Input: release 1.9.11.NN, the dev ticket(s)/PR id(s), the partner keys (e.g. raiffeisen mkb bb). Optional: tester/reviewer names, dates, and whether the change is core (shared text) or partner-specific.
  2. Resolve partners via partners.json → display name, YouTrack project, default environment. Unknown key → ask the user (display name + project), then offer to persist it.
  3. Gather context (read-only): the dev ticket via the existing fkticket client (fetch_issue: summary, description, comments, links); optionally the linked GitHub PR diff via gh pr diff / git (the fkticket client is YouTrack-only); and one recent past report per partner (download + macOS textutil → txt) as a house-style reference.
  4. Draft per partner: produce the renderer input JSON — metadata + environment + test cases (title/description/expected) + tester & reviewer evaluation prose + igen/nem verdict. Reuse one shared draft for a core release; tailor otherwise.
  5. Render: for each partner, write out/<partner>.json and run the renderer → out/tesztjegyzokonyv_<partner>_<version>.docx.
  6. Hand-off report: list generated files + the remaining manual steps (paste screenshots into each Evidencia block, underline the correct Sikeres/sikertelen + igen/nem, export to PDF, attach to each partner’s release ticket). No auto-write to YouTrack.

The renderer — render_tjk.py (stdlib only)

Python 3, stdlib only (zipfile, re, shutil, html, json, sys). Signature: render_tjk.py <sablon.docx> <input.json> <output.docx>. Pure-read of the sablon + write to out/; never mutates the sablon.

  • Substitution rule (all fields): values are XML-escaped (html.escape(v, quote=False)). A value with newlines is split on \n and rejoined as …</w:t><w:br/><w:t xml:space="preserve">… so Word renders real line breaks (a literal \n inside a <w:t> would not break the line). True bulleted lists are not synthesized in v1.
  • Test-case cloning: the repeatable block is paragraphs 27–36 of document.xml, anchored precisely (6 Heading2 paragraphs exist, so “the Heading2” is ambiguous): start = first Heading2 <w:p> whose text contains teszteset (uniquely para 27); end = first <w:p> containing aláhúzandó (para 36; the verdict’s second occurrence is para 43, outside the block). For each test case k (1-based): copy the span, replace literal 1.k., substitute the 4 test-case placeholders, leave the <képernyőképek…> cue intact when evidence is empty. Concatenate and splice back. Empty testCases → original single block untouched.
  • Repackage: open the sablon with zipfile, copy every entry’s bytes verbatim except word/document.xml (preserving each entry’s ZipInfo + compression). Does not extractall/re-zip (that reorders parts and risks corruption). No new parts added → [Content_Types].xml untouched.
  • Self-check (asserts, non-zero exit on failure): every metadata + summary token is absent from the output XML; the count of teszteset – headings equals max(1, len(testCases)); the output opens as a valid zip and document.xml is well-formed. __main__ runs the self-check against the pinned sablon from a fixture (2 cases, one multi-line field) — the single always-runnable check.

The partner map — partners.json

{ "<key>": { "display": "...", "ytProject": "...", "defaultEnv": "..." } }. 13 partners seeded (only those that actually ship releases), extended lazily: barion, bb, cib, cofidis, dap, fundamenta, generali, instacash, microsec, mkb, mvm, raiffeisen, unicredit. defaultEnv defaults to Fejlesztői lokál környezet. Exact display strings + ytProject are confirmed at build time against a recent ticket per partner (e.g. microsec → MF, dap → ASSDAP, instacash → display "InstaCash" / ASSICASH — added 2026-06-26, see First real use — InstaCash eSign 1.3.0.11).

v1 scope — what stays manual

Manual / out of scope in v1

  • Evidence (screenshots) — the renderer leaves the <képernyőképek…> placeholder intact as a visible “paste here” cue.
  • Final pass/fail underlineSikeres / sikertelen and igen / nem are surfaced in the hand-off note; the doc keeps the “underline the correct one” convention (no underline formatting written).
  • PDF export — testers currently export from Word (a future option: soffice --headless --convert-to pdf).
  • Attaching to YouTrack — deferred; would be write-gated by the fk-ticket analyze guard. No YouTrack write-back at all in v1.
  • Pre-mapping all 39 partners — added on demand.

Verified working (2026-06-26)

  • Renderer self-check + tests/test_render.py pass.
  • An independent fixture (evidence-provided, single test case, multi-line field) renders correctly — <w:br/> injected for line breaks, headings numbered, tokens substituted.
  • The pinned sablon is byte-identical and unmutated after a render (renderer only writes to out/).
  • Not yet verified (deferred to first real use): that a Word-opened render visually matches the sablon’s branding/fonts across all 4 test-case fields — covered by the render test + manual acceptance.

First real use — InstaCash eSign 1.3.0.11

First production render (2026-06-26) — and the first InstaCash eSign TJK ever

The flow was dogfooded to produce the test report for the InstaCash eSign 1.3.0.11 release. This is notable because InstaCash historically had no tesztjegyzőkönyv at all (see youtrack-tesztjegyzokonyv-attachment-recipe) — this is the first one.

  • Partner added: instacash{ display: "InstaCash", ytProject: "ASSICASH" } in partners.json (12 → 13 seeded partners). The eSign release tracks under ASSICASH-92.
  • Rendered: ~/Downloads/tesztjegyzokonyv_instacash_1.3.0.11.docx5 test cases (the renderer’s test-case cloning exercised beyond the 2-case fixture).
  • Source release: eSign 1.3.0.11 (esign_oss + esign_css), dev ticket FKITDEV-8817 (jQuery CVE remediation + HSTS/nginx/WAF hardening).
  • Manual remainder (per v1 scope): screenshots, underline the Sikeres/sikertelen + igen/nem verdicts, PDF export, and attach to YouTrack are still hand steps — the docx is the draft body, not the attached artifact.
  • youtrack-tesztjegyzokonyv-attachment-recipe — the finding/downloading companion: where TJKs live in YouTrack (ASS<CLIENT> / BUG<CLIENT> attachments), the read-only REST recipe, the 8-section legacy structure, and source-of-truth template tickets FKITDEV-8329 / FKITDEV-8330
  • client-registry — YouTrack suffix ≠ repo name; needed to resolve a partner’s ytProject
  • release-process — per-client tagging / build / deploy workflow that produces these test artifacts
  • release-automation-design/fk-release design; the broader release-prep flow (TJK generation slots into the test-evidence step)
  • FaceKom Releases — release hubs; TJKs are per-release deliverables
  • instacash-esign-1.3.0.11 — the first release this flow generated a TJK for (and the first InstaCash eSign TJK)
  • rtk-mangles-curl-and-pipes — why context-gathering uses python urllib / gh, not curl | …
  • FaceKom — platform overview