Axis Closure Matrix
Purpose
EITR's architecture has more surface area than can be audited all at once, and open-ended "let's
review the whole thing again" passes never converge — any sufficiently complex codebase has
near-infinite room for "could be more complete," so a fully open audit just burns tokens without
ever reaching a release-ready verdict. This skill exists to replace that loop with a bounded
per-axis process: pick one architecture area, research what a genuinely solid version of it needs
from real external sources (never from memory), compare it line-by-line against what EITR currently
does, and stop at an explicit, checkable Definition of Done — not at "looks good enough."
An axis qualifies for a single pass of this skill only if it maps to at most 3
independently-versioned subsystems (e.g. "CI/CD generator" = 4 CI providers sharing one
cicd.ts source = 1 subsystem; "AI-agent layer" = agents + skills + MCP bridge + slash-commands =
4 independently-versioned subsystems, so it does NOT qualify as one axis) and is expected to
produce at most ~15 Core+Extended table rows. Examples that qualify as one axis: "the
TS+Playwright CPOM base," "the CI/CD generator," "the Python CPOM base." If the named target
exceeds either bound — "the AI-agent layer," "the entire codebase," or anything you cannot map to
a single noun phrase after 1-2 clarifying questions — do not run the full process against it as
one axis; instead propose 2-4 named sub-axes (e.g. "AI-agent layer" → "agent definitions,"
"skill definitions," "MCP bridge," "slash-command layer") and ask the user which one to start
with.
When to use
Good trigger — user names one qualifying axis and asks for research/matrix/closure status:
"матрица по оси CI/CD генератора", "проверь ось Python CPOM base", "что осталось по TS+Playwright базе". Proceed directly.
Bad trigger — do not proceed, ask first — the request names no axis, or names one that fails
the size bound above: "давай ещё раз всё перепроверим" (no axis named — ask which one),
"проверь AI-слой целиком" (fails the ≤3-subsystem bound — propose the sub-axis split above and
ask which sub-axis to start with).
Never invoke this skill proactively to suggest auditing some other part of the codebase on your
own initiative — that reintroduces the exact unbounded-audit loop this skill was created to end.
Step 0 — check for a prior closure before starting new research. Before doing any research,
run this assistant's artifact/document-listing capability (or ask the user for the link if you
suspect one exists outside this session) and look for an existing report whose title matches this
axis. If one exists and its Definition of Done was met (status ЗАКРЫТА), do not start new
research — ask the user to name which specific re-open trigger from step 4 applies before
proceeding. If no matching closed report exists, or the user names a valid trigger, proceed to
step 1.
The process (four deliverables, in order)
Real, cited research. Never invent what a solid version of the axis needs from memory — every
requirement in the table must trace to a source that is either (a) the tool/platform's own
official documentation, (b) a GitHub repository with ≥1,000 stars (≥500 stars if the axis's tool
is itself a niche/low-adoption one), or (c) a post on the tool's own engineering blog. Sources
outside these three categories do not count as citable evidence for a Core/Extended
classification. Delegate the research to a dedicated web-research agent/subagent whenever the
axis touches 3 or more distinct external tools/platforms/vendors (e.g. 4 CI providers); do
the research directly yourself when it touches 1-2. When delegating, give the agent the current
EITR code for the axis as context and a numbered list of exactly what needs a citable answer,
and require every claim in its report to name a source URL meeting the criteria above.
- If no source meeting the criteria above resolves a question, mark it unresolved — do not
guess a verdict either way.
- If two sources that both meet the criteria above directly conflict on the same row, do not pick
one — mark the row
—/unresolved in the Core/Extended column and quote both conflicting claims
verbatim in "Действие," naming both sources.
One consolidated Core/Extended table. Columns, in this exact order:
Категория | Core/Ext | Что говорит ресёрч | Реализовано | Протестировано вживую | Регрессионные тесты | Действие.
- Core if, and only if, its absence would break CPOM contract checks, break CI, or produce
incorrect generated code in at least 1 of the languages/systems this axis covers — a
correctness/contract test, not a subjective feel.
- Extended if it only applies to a subset of possible target-project shapes (a project type,
a scale, an optional integration) and can be fully covered by documenting it as an opt-in
pattern with zero unconditionally-generated code — do not pad the framework with something a
given project may never need just to raise a score.
- "Что говорит ресёрч" must carry a citation meeting step 1's source criteria for every row, not
just a claim.
- "Реализовано" (Да/Нет/Частично +
file:line): grounded in an actual read of the current
source — never assumed from a prior audit or from the template's own docstring/description.
Verify a check's real scope empirically (read the code) rather than trusting what its name
implies. This column answers only "does the code exist," nothing about whether it works.
- "Протестировано вживую" (Да/Нет + what was actually run): answers "was this row's exact
behavior executed for real at least once," not "does a unit test exist for it." Да requires at
minimum System-level execution per the four levels below; a passing unit/integration test
alone is Нет here, even if it's green. Be honest when the answer is Нет because the real
external target isn't available to this session (e.g. no live CI-provider server to push to) —
record that as the reason, don't leave the cell ambiguous or skip it.
- "Регрессионные тесты" (which of the four levels below exist, or "нет"): what automated,
repeatable coverage protects this row going forward, independent of whether it happened to get
live-tested this pass. Name the actual test file(s), not just the level.
- Unit — a test asserting one render/generator function's output content in isolation
(string/AST assertion against its return value), no filesystem or process execution.
- Integration — a test asserting multiple generators' combined output together in-memory
(e.g.
plan()'s full file list/content for a given profile), still no real toolchain run.
- System — a test that writes a real generated project to disk and executes the real
target toolchain against it end-to-end (e.g. actually running
mvn test/`gradle
test/pytest/npm test` against freshly generated output) — proves the generated artifact
actually works standalone, not just that the generator produced plausible-looking text.
- Acceptance — the generated artifact exercised against the real external system it's
built for, outside EITR's own test harness (an actual GitHub Actions run on a real repo, a
real GitLab CI pipeline, a real TeamCity server build). Often infeasible inside a single
session with no access to that external system — mark it honestly absent rather than
claiming it.
- A row you could not resolve to Core or Extended with real evidence gets
— in that column and
an explicit note in "Действие" that it needs a follow-up lookup — never force a guess into
Core or Extended just to fill the cell.
- Every claimed gap must be real and verified, never invented to make the matrix look more
rigorous — this mirrors the project's own scoring-methodology standard: a gap is only a gap if
it is grounded in an actual file, missing capability, or genuine limitation you checked.
Worked example row (format reference, not literal content to reuse):
Auth bootstrap | Core | Playwright docs recommend storageState reuse across the whole suite (playwright.dev/docs/auth) | Да, packages/engine/src/plan/templates/auth-setup.ts:12 | Да — real generated project, real Playwright test run against a live app | System (packages/cli/test/e2e.full-cycle.test.ts), Integration (plan.matrix.test.ts); no Acceptance (never run in a real CI provider) | none — closed
An explicit, checkable Definition of Done. State the exact condition under which the axis
counts as closed — normally: every Core row has "Реализовано" = Да, has at least System-level
coverage in "Регрессионные тесты" (Unit/Integration alone is not enough for a Core row — a test
that never actually runs the generated output is not proof it works), every Extended row has a
recorded rationale for staying Extended, and zero rows are in an unresolved "missing/buggy"
state. A Core row with "Протестировано вживую" = Нет does not by itself block closure — being
honest about it does — as long as System-level regression coverage exists and the reason live/
Acceptance-level testing wasn't possible this pass is stated (e.g. no access to a real CI-provider
server). If any Core row is still open on implementation or lacks System-level regression
coverage, the axis is not closed — say so plainly (open axis, punch list of what's left)
rather than rounding up to "basically done."
Explicit re-open triggers. Name the specific future external events that would legitimately
justify revisiting this axis later (a new major version of a tool the axis depends on, a real
user-reported bug in a Core row, new official guidance superseding a row). A new internal audit
finding something on its own initiative is explicitly NOT a valid re-open trigger — say this in
the report itself, every time. That is precisely the loop this skill exists to prevent.
Report shape (deterministic HTML template)
Load this assistant's design/formatting guidance before writing the file, if one is configured.
Reuse this structure and token system for every axis matrix so they read as one consistent series
regardless of axis or date — only the content changes, not the shape:
- A
kicker line stating which axis this is, its explicit scope boundary (what's deliberately
excluded, if anything), and current status (ОТКРЫТА / ЗАКРЫТА).
- A short "Итог ресёрча" paragraph — 2-4 sentences, prose, citing the strongest 1-2 sources.
- A stat-row summarizing counts: confirmed bugs, Core gaps, Extended/OK-as-is, already-correct
rows, and unresolved-by-research rows — so the reader gets the shape of the matrix before the
table itself.
- The Core/Extended table itself, using the 7-column schema from step 2, with badge tags for
Core/Extended and color-coded status (green Да / red Нет / grey) for both "Реализовано" and
"Протестировано вживую" — reuse the color tokens already established in this repo's prior axis
reports. "Регрессионные тесты" is plain text naming the levels and files, not a badge.
- A "Definition of Done" callout — green/
done styling only if every Core row is actually closed,
otherwise amber/open styling with the explicit punch list of what remains.
- A "Триггеры на переоткрытие" callout listing the legitimate re-open triggers from step 4,
including the explicit "NOT a trigger" line about self-initiated audits.
- A footer naming the real sources consulted and the date.
Base the palette and type choices on the axis's own subject matter (a CI/CD matrix can read
differently from a language-runtime matrix) rather than reusing one hardcoded hex palette verbatim
— choose a considered, non-default palette, but keep the same layout skeleton, column schema, and
section order across axes.
After publishing
Report back in Russian (per this repo's own AGENTS.md language rule): the artifact link, whether
the axis is closed or open, and — if open — the short punch list of remaining Core gaps. Do not
restate the full table in chat; the artifact is the record. Do not propose which axis to do next
unless the user asks.
Anti-patterns this skill exists to prevent
- Re-running the same axis "just to double-check" without a new re-open trigger from step 4.
- Scoring or closing more than one axis in a single pass — pick one, finish it, stop.
- Treating "the code looks fine on a skim" as equivalent to "verified against cited research" —
every Core/Extended classification needs both a citation and a file:line check, not either alone.
- Rounding an open axis (any unresolved Core row) up to closed because most of the table is green.
1---2name: axis-closure-matrix3description: Produces a research-backed Core/Extended gap matrix for exactly ONE named EITR architecture axis (e.g. "CPOM base for Python", "CI/CD generator", "AI-agent layer") at a time, ending in a checkable Definition of Done and explicit re-open triggers instead of an open-ended audit. Trigger only when the user explicitly names a specific axis and asks to research/score/close it — phrases like "матрица по оси X", "closure-план для X", "проверь ось X", "что осталось по X". Never self-invoke to propose a new axis on your own initiative.4---56# Axis Closure Matrix78## Purpose910EITR's architecture has more surface area than can be audited all at once, and open-ended "let's11review the whole thing again" passes never converge — any sufficiently complex codebase has12near-infinite room for "could be more complete," so a fully open audit just burns tokens without13ever reaching a release-ready verdict. This skill exists to replace that loop with a **bounded**14per-axis process: pick one architecture area, research what a genuinely solid version of it needs15from real external sources (never from memory), compare it line-by-line against what EITR currently16does, and stop at an explicit, checkable Definition of Done — not at "looks good enough."1718An axis qualifies for a single pass of this skill only if it maps to **at most 319independently-versioned subsystems** (e.g. "CI/CD generator" = 4 CI providers sharing one20`cicd.ts` source = 1 subsystem; "AI-agent layer" = agents + skills + MCP bridge + slash-commands =214 independently-versioned subsystems, so it does NOT qualify as one axis) **and** is expected to22produce **at most ~15 Core+Extended table rows**. Examples that qualify as one axis: "the23TS+Playwright CPOM base," "the CI/CD generator," "the Python CPOM base." If the named target24exceeds either bound — "the AI-agent layer," "the entire codebase," or anything you cannot map to25a single noun phrase after 1-2 clarifying questions — do not run the full process against it as26one axis; instead propose 2-4 named sub-axes (e.g. "AI-agent layer" → "agent definitions,"27"skill definitions," "MCP bridge," "slash-command layer") and ask the user which one to start28with.2930## When to use3132**Good trigger** — user names one qualifying axis and asks for research/matrix/closure status:33`"матрица по оси CI/CD генератора"`, `"проверь ось Python CPOM base"`, `"что осталось по34TS+Playwright базе"`. Proceed directly.3536**Bad trigger — do not proceed, ask first** — the request names no axis, or names one that fails37the size bound above: `"давай ещё раз всё перепроверим"` (no axis named — ask which one),38`"проверь AI-слой целиком"` (fails the ≤3-subsystem bound — propose the sub-axis split above and39ask which sub-axis to start with).4041Never invoke this skill proactively to suggest auditing some other part of the codebase on your42own initiative — that reintroduces the exact unbounded-audit loop this skill was created to end.4344**Step 0 — check for a prior closure before starting new research.** Before doing any research,45run this assistant's artifact/document-listing capability (or ask the user for the link if you46suspect one exists outside this session) and look for an existing report whose title matches this47axis. If one exists and its Definition of Done was met (status `ЗАКРЫТА`), do not start new48research — ask the user to name which specific re-open trigger from step 4 applies before49proceeding. If no matching closed report exists, or the user names a valid trigger, proceed to50step 1.5152## The process (four deliverables, in order)53541. **Real, cited research.** Never invent what a solid version of the axis needs from memory — every55 requirement in the table must trace to a source that is either (a) the tool/platform's own56 official documentation, (b) a GitHub repository with ≥1,000 stars (≥500 stars if the axis's tool57 is itself a niche/low-adoption one), or (c) a post on the tool's own engineering blog. Sources58 outside these three categories do not count as citable evidence for a Core/Extended59 classification. Delegate the research to a dedicated web-research agent/subagent whenever the60 axis touches **3 or more** distinct external tools/platforms/vendors (e.g. 4 CI providers); do61 the research directly yourself when it touches 1-2. When delegating, give the agent the current62 EITR code for the axis as context and a numbered list of exactly what needs a citable answer,63 and require every claim in its report to name a source URL meeting the criteria above.64 - If no source meeting the criteria above resolves a question, mark it **unresolved** — do not65 guess a verdict either way.66 - If two sources that both meet the criteria above directly conflict on the same row, do not pick67 one — mark the row `—`/unresolved in the Core/Extended column and quote both conflicting claims68 verbatim in "Действие," naming both sources.69702. **One consolidated Core/Extended table.** Columns, in this exact order:71 `Категория | Core/Ext | Что говорит ресёрч | Реализовано | Протестировано вживую |72Регрессионные тесты | Действие`.73 - **Core** if, and only if, its absence would break CPOM contract checks, break CI, or produce74 incorrect generated code in at least 1 of the languages/systems this axis covers — a75 correctness/contract test, not a subjective feel.76 - **Extended** if it only applies to a subset of possible target-project shapes (a project type,77 a scale, an optional integration) and can be fully covered by documenting it as an opt-in78 pattern with zero unconditionally-generated code — do not pad the framework with something a79 given project may never need just to raise a score.80 - "Что говорит ресёрч" must carry a citation meeting step 1's source criteria for every row, not81 just a claim.82 - **"Реализовано"** (Да/Нет/Частично + `file:line`): grounded in an actual read of the current83 source — never assumed from a prior audit or from the template's own docstring/description.84 Verify a check's real scope empirically (read the code) rather than trusting what its name85 implies. This column answers only "does the code exist," nothing about whether it works.86 - **"Протестировано вживую"** (Да/Нет + what was actually run): answers "was this row's exact87 behavior executed for real at least once," not "does a unit test exist for it." Да requires at88 minimum **System**-level execution per the four levels below; a passing unit/integration test89 alone is Нет here, even if it's green. Be honest when the answer is Нет because the real90 external target isn't available to this session (e.g. no live CI-provider server to push to) —91 record that as the reason, don't leave the cell ambiguous or skip it.92 - **"Регрессионные тесты"** (which of the four levels below exist, or "нет"): what automated,93 repeatable coverage protects this row going forward, independent of whether it happened to get94 live-tested this pass. Name the actual test file(s), not just the level.95 - **Unit** — a test asserting one render/generator function's output content in isolation96 (string/AST assertion against its return value), no filesystem or process execution.97 - **Integration** — a test asserting multiple generators' combined output together in-memory98 (e.g. `plan()`'s full file list/content for a given profile), still no real toolchain run.99 - **System** — a test that writes a real generated project to disk and executes the real100 target toolchain against it end-to-end (e.g. actually running `mvn test`/`gradle101test`/`pytest`/`npm test` against freshly generated output) — proves the generated artifact102 actually works standalone, not just that the generator produced plausible-looking text.103 - **Acceptance** — the generated artifact exercised against the real external system it's104 built for, outside EITR's own test harness (an actual GitHub Actions run on a real repo, a105 real GitLab CI pipeline, a real TeamCity server build). Often infeasible inside a single106 session with no access to that external system — mark it honestly absent rather than107 claiming it.108 - A row you could not resolve to Core or Extended with real evidence gets `—` in that column and109 an explicit note in "Действие" that it needs a follow-up lookup — never force a guess into110 Core or Extended just to fill the cell.111 - Every claimed gap must be real and verified, never invented to make the matrix look more112 rigorous — this mirrors the project's own scoring-methodology standard: a gap is only a gap if113 it is grounded in an actual file, missing capability, or genuine limitation you checked.114115 **Worked example row** (format reference, not literal content to reuse):116 `Auth bootstrap | Core | Playwright docs recommend storageState reuse across the whole suite117(playwright.dev/docs/auth) | Да, packages/engine/src/plan/templates/auth-setup.ts:12 | Да — real118generated project, real Playwright test run against a live app | System119(packages/cli/test/e2e.full-cycle.test.ts), Integration (plan.matrix.test.ts); no Acceptance (never120run in a real CI provider) | none — closed`1211223. **An explicit, checkable Definition of Done.** State the exact condition under which the axis123 counts as closed — normally: every Core row has "Реализовано" = Да, has at least System-level124 coverage in "Регрессионные тесты" (Unit/Integration alone is not enough for a Core row — a test125 that never actually runs the generated output is not proof it works), every Extended row has a126 recorded rationale for staying Extended, and zero rows are in an unresolved "missing/buggy"127 state. A Core row with "Протестировано вживую" = Нет does **not** by itself block closure — being128 honest about it does — as long as System-level regression coverage exists and the reason live/129 Acceptance-level testing wasn't possible this pass is stated (e.g. no access to a real CI-provider130 server). If any Core row is still open on implementation or lacks System-level regression131 coverage, the axis is **not** closed — say so plainly (open axis, punch list of what's left)132 rather than rounding up to "basically done."1331344. **Explicit re-open triggers.** Name the specific future external events that would legitimately135 justify revisiting this axis later (a new major version of a tool the axis depends on, a real136 user-reported bug in a Core row, new official guidance superseding a row). **A new internal audit137 finding something on its own initiative is explicitly NOT a valid re-open trigger** — say this in138 the report itself, every time. That is precisely the loop this skill exists to prevent.139140## Report shape (deterministic HTML template)141142Load this assistant's design/formatting guidance before writing the file, if one is configured.143Reuse this structure and token system for every axis matrix so they read as one consistent series144regardless of axis or date — only the content changes, not the shape:145146- A `kicker` line stating which axis this is, its explicit scope boundary (what's deliberately147 excluded, if anything), and current status (`ОТКРЫТА` / `ЗАКРЫТА`).148- A short "Итог ресёрча" paragraph — 2-4 sentences, prose, citing the strongest 1-2 sources.149- A stat-row summarizing counts: confirmed bugs, Core gaps, Extended/OK-as-is, already-correct150 rows, and unresolved-by-research rows — so the reader gets the shape of the matrix before the151 table itself.152- The Core/Extended table itself, using the 7-column schema from step 2, with badge tags for153 Core/Extended and color-coded status (green Да / red Нет / grey) for both "Реализовано" and154 "Протестировано вживую" — reuse the color tokens already established in this repo's prior axis155 reports. "Регрессионные тесты" is plain text naming the levels and files, not a badge.156- A "Definition of Done" callout — green/`done` styling only if every Core row is actually closed,157 otherwise amber/`open` styling with the explicit punch list of what remains.158- A "Триггеры на переоткрытие" callout listing the legitimate re-open triggers from step 4,159 including the explicit "NOT a trigger" line about self-initiated audits.160- A footer naming the real sources consulted and the date.161162Base the palette and type choices on the axis's own subject matter (a CI/CD matrix can read163differently from a language-runtime matrix) rather than reusing one hardcoded hex palette verbatim164— choose a considered, non-default palette, but keep the same layout skeleton, column schema, and165section order across axes.166167## After publishing168169Report back in Russian (per this repo's own AGENTS.md language rule): the artifact link, whether170the axis is closed or open, and — if open — the short punch list of remaining Core gaps. Do not171restate the full table in chat; the artifact is the record. Do not propose which axis to do next172unless the user asks.173174## Anti-patterns this skill exists to prevent175176- Re-running the same axis "just to double-check" without a new re-open trigger from step 4.177- Scoring or closing more than one axis in a single pass — pick one, finish it, stop.178- Treating "the code looks fine on a skim" as equivalent to "verified against cited research" —179 every Core/Extended classification needs both a citation and a file:line check, not either alone.180- Rounding an open axis (any unresolved Core row) up to closed because most of the table is green.