Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ All notable changes to `cursor-rules` will be documented in this file.

## [Unreleased]

- ✨ **Added** `feat(compound-engineering)`: every agent/skill that creates a tracker issue now **selects and assigns the most relevant existing label** as part of issue creation (#734). New canonical section `@rules/compound-engineering/general.mdc` *Assign the most relevant existing label when creating a tracker issue* — enumerate the tracker's existing labels (`gh label list --json name,description` on GitHub), match by type + domain, never invent a new label or fall back to a random one, and create the issue unlabelled when nothing genuinely fits; the sanctioned `EPIC` label stays the sole documented exception. Referenced from `skills/create-issue/SKILL.md`, `skills/create-issues-from-text/SKILL.md`, `skills/blueprint/SKILL.md`, and `skills/product-capability/SKILL.md`. Pinned by `tests/Installer/CompoundEngineeringContentTest.php` and `tests/Installer/SkillsContentTest.php`.

- ✨ **Added** `feat(code-review)`: every code review now walks a new **Self-Documenting Code — Comment & Doc Hygiene** lens (#733) — for every comment / PHPDoc / inline doc the diff adds or modifies, flag redundant *what*-narration that restates what the code already says and require its deletion, while never flagging the two preserved exceptions: rationale / considered alternatives / domain language (belongs in ADRs & glossaries) and navigation pointers (`@rules/…`, `@skills/…`, links to collaborating classes/methods). Documented in `@rules/code-review/general.mdc` *Self-Documenting Code — Comment & Doc Hygiene Analysis*, referenced from `skills/code-review/SKILL.md`'s Core Analysis walk (inherited by every CR wrapper), pinned by `tests/Installer/CodeReviewContentTest.php`.

- 📝 **Changed**: every code review now runs **`class-refactoring` with `MODE=cr` across its complete guideline set**, and **every item the lens returns reaches the published report**. The read-only lens was already in the always-run set of all four CR skills (`code-review`, `code-review-github`, `code-review-jira`, `code-review-bugsnag`), but each invocation described it narrowly ("DRY duplication, single-responsibility breaches, oversized methods") and the diff-scoped checklist in `@rules/code-review/general.mdc` was a **closed six-bullet list** — so a reviewer reading either literally walked a fraction of what the skill defines and the rest never made it into the report. The closed lists are now explicitly the **high-frequency subset, not the boundary of the walk**: speculative interfaces, pass-through Actions, `>4` parameters → DTO, Simplicity First, business-logic-layer placement, Repository scope, query performance non-regression, intention-revealing extraction, naming, and nesting depth are walked too. A new **Routing & no-drop contract** (`@rules/code-review/general.mdc` *Refactoring & Tech Debt (DRY) Analysis — diff-scoped detail*, step 5) says where each returned item lands: an item whose underlying rule declares a severity goes to its **Critical / Moderate / Minor** bucket with the four reproducer fields (a SQL performance item to `## Database Analysis`), everything else to **Refactoring (DRY / tech debt)** / **Refactoring proposals** — and a violation already raised by the Core Analysis / Strict rule compliance walk is kept there rather than duplicated, so each violation is reported exactly once. `@skills/class-refactoring/SKILL.md` gains the matching **Completeness contract** in *Modes* and now returns the **matched guideline** with every item so the CR can route and de-duplicate it; the four CR output templates ask for that guideline in the `Why:` field on lens-produced items. The walked-guideline list lives **only** in the rule — the four CR skills reference it instead of restating it, so the next guideline added to `class-refactoring` cannot drift across five files. Pinned by `tests/Installer/CodeReviewContentTest.php` (*every CR walks the full class-refactoring guideline set and drops no returned item*). Per user request — *při jakémkoliv CR chci, aby se spustil i skill class-refactoring v readonly mode a do reportu připsal i věci, které jsou definované v tomto skillu*.
Expand Down
14 changes: 14 additions & 0 deletions rules/compound-engineering/general.mdc
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,20 @@ Any run that begins implementing a tracker issue **must claim it atomically befo

The per-tracker mechanics (claim label name, helper script call, selection query negation) live in `@skills/resolve-issue/SKILL.md` and `@skills/autoresolve-oldest-github-issue/SKILL.md`. This section owns the principle; those skills own the execution.

## Assign the most relevant existing label when creating a tracker issue

Any agent or skill that creates a tracker issue — GitHub or JIRA — must select and assign the most relevant existing label to it as part of issue creation. Creating an issue with no thought given to labelling is an incomplete creation step.

- **Select from what already exists, never invent.** List the tracker's existing labels, match the issue's type (bug / feat / docs / chore / ...) and domain against that list, and assign the closest match. Never mint a new label ad hoc, and never fall back to a random or first-available label when nothing actually fits — an unrelated label is worse than none.
- **No relevant match → create without a label.** When none of the existing labels are a genuine match, create the issue unlabelled rather than force a bad fit. This is the expected, correct outcome, not an error to work around.
- **GitHub mechanics.** `gh label list --json name,description` to read the repository's current label set, pick the closest match by type + domain, then `gh issue create ... --label "<name>"` — the command itself enforces existing-only, since it fails on a label name that does not already exist, so there is no accidental path to minting one this way.
- **`EPIC` is the sole sanctioned exception.** `@skills/create-issues-from-text/SKILL.md` "EPIC parent & sub-issues" deliberately creates and applies the `EPIC` label for a cross-cutting parent issue; that is a documented, intentional label, not a violation of "never invent" above.
- **Idempotent.** Assigning a label that is already present on the issue is a no-op — never fail or duplicate over it.
- **JIRA is a secondary path.** JIRA labels are free text rather than a fixed, enumerable set, and `acli` carries its own limits (see the project's `acli-jira-quirks` memory entry) — apply the same select-don't-invent principle wherever the tooling allows enumerating existing labels, but do not block issue creation solely because label enumeration is imperfect in JIRA.
- **Bugsnag does not apply.** Bugsnag errors are not tracker issues an agent authors from scratch; this rule scopes to trackers where the agent creates a new issue (GitHub, JIRA).

This section owns the principle; the issue-creating skills reference it and own the execution — `@skills/create-issue/SKILL.md`, `@skills/create-issues-from-text/SKILL.md`, `@skills/blueprint/SKILL.md`, `@skills/product-capability/SKILL.md`.

## What Not To Do

- Do not let a durable lesson live only in a commit message or a closed PR thread — promote the reusable part into the project's memory file.
Expand Down
1 change: 1 addition & 0 deletions skills/blueprint/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ metadata:
## Constraints
- Apply `@rules/git/general.mdc` — branch, commit, and PR conventions below come from it.
- Apply `@rules/compound-engineering/general.mdc` — the plan is durable memory the next agent reuses, not throwaway prose.
- Apply `@rules/compound-engineering/general.mdc` *Assign the most relevant existing label when creating a tracker issue* for any tracker issue this plan creates or hands off to `@skills/create-issues-from-text/SKILL.md` to create.
- Apply `@rules/laravel/architecture.mdc` when the project uses `pekral/arch-app-services`, so each step lands in the correct layer.
- Plan only. Do not implement, commit, or push any step.
- Output Markdown only. English only.
Expand Down
1 change: 1 addition & 0 deletions skills/create-issue/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ Create a well-formatted issue while preserving the original content exactly.
### 3. Create Issue
- Use available CLI tool
- Set title and formatted description
- Assign the most relevant existing label (per `@rules/compound-engineering/general.mdc` *Assign the most relevant existing label when creating a tracker issue*)
- Assign to current user

### 4. Output
Expand Down
1 change: 1 addition & 0 deletions skills/create-issues-from-text/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ Split a complex assignment into multiple clear, structured issues.
### 3. Create Issues
- One issue per step
- Ensure each is independently deliverable
- Assign the most relevant existing label to each issue (per `@rules/compound-engineering/general.mdc` *Assign the most relevant existing label when creating a tracker issue*)

### 4. Output
- Return list of created issues with URLs
Expand Down
1 change: 1 addition & 0 deletions skills/product-capability/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ metadata:
## Constraints
- Apply `@rules/laravel/architecture.mdc` — actors, surfaces, states, and data model must fit the existing layers (Action → ModelService → Repository / ModelManager), not invent new abstractions.
- Apply `@rules/compound-engineering/general.mdc` — the plan is a durable artifact the next agent reuses, not throwaway prose.
- Apply `@rules/compound-engineering/general.mdc` *Assign the most relevant existing label when creating a tracker issue* for any tracker issue this plan creates or hands off to `@skills/create-issues-from-text/SKILL.md` to create.
- Do not invent product truth. Every unknown is an explicit open question, never a silent assumption.
- Separate user-visible promises from implementation detail. Keep them in distinct sections.
- Mark each constraint as **fixed policy**, **architectural preference**, or **open question** — never blur the three.
Expand Down
36 changes: 36 additions & 0 deletions tests/Installer/CompoundEngineeringContentTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,42 @@
expect($content)->toContain('@skills/autoresolve-oldest-github-issue/SKILL.md');
});

test('compound-engineering rule mandates assigning the most relevant existing label on issue creation (issue #734)', function (): void {
$packageDir = dirname(__DIR__, 2);
$content = (string) file_get_contents($packageDir . '/rules/compound-engineering/general.mdc');

// The section heading must exist.
expect($content)->toContain('## Assign the most relevant existing label when creating a tracker issue');
expect($content)->toContain('most relevant existing label');

// GitHub mechanics: enumerate existing labels before assigning.
expect($content)->toContain('gh label list --json name,description');

// No-random-label behaviour: never invent, never fall back to a random label, unlabelled is fine.
expect($content)->toContain('never invent');
expect($content)->toContain('never fall back to a random or first-available label');
expect($content)->toContain('create the issue unlabelled rather than force a bad fit');

// The EPIC label stays the sole sanctioned exception.
expect($content)->toContain('`EPIC` is the sole sanctioned exception');

// Reference the issue-creating skills that inherit this rule.
expect($content)->toContain('@skills/create-issue/SKILL.md');
expect($content)->toContain('@skills/create-issues-from-text/SKILL.md');
expect($content)->toContain('@skills/blueprint/SKILL.md');
expect($content)->toContain('@skills/product-capability/SKILL.md');

$createIssue = (string) file_get_contents($packageDir . '/skills/create-issue/SKILL.md');
$createIssuesFromText = (string) file_get_contents($packageDir . '/skills/create-issues-from-text/SKILL.md');
$blueprint = (string) file_get_contents($packageDir . '/skills/blueprint/SKILL.md');
$productCapability = (string) file_get_contents($packageDir . '/skills/product-capability/SKILL.md');

foreach ([$createIssue, $createIssuesFromText, $blueprint, $productCapability] as $skillContent) {
expect($skillContent)->toContain('Assign the most relevant existing label');
expect($skillContent)->toContain('@rules/compound-engineering/general.mdc');
}
});

test('compound-engineering rule mandates temporary-file hygiene with a hard memory-files exception (issue #694)', function (): void {
$packageDir = dirname(__DIR__, 2);
$content = (string) file_get_contents($packageDir . '/rules/compound-engineering/general.mdc');
Expand Down
25 changes: 25 additions & 0 deletions tests/Installer/SkillsContentTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -960,3 +960,28 @@
expect($content)->toContain('skills/_shared/scan-attachments.sh');
expect($content)->toContain('Read only files under `safe/`');
});

test('every issue-creating skill carries a byte-identical reference to the most-relevant-existing-label rule (issue #734)', function (): void {
$packageDir = dirname(__DIR__, 2);

$labelRuleReference = '`@rules/compound-engineering/general.mdc` *Assign the most relevant existing label when creating a tracker issue*';

$createIssue = (string) file_get_contents($packageDir . '/skills/create-issue/SKILL.md');
expect($createIssue)->toContain(
'- Assign the most relevant existing label (per ' . $labelRuleReference . ')',
);

$createIssuesFromText = (string) file_get_contents($packageDir . '/skills/create-issues-from-text/SKILL.md');
expect($createIssuesFromText)->toContain(
'- Assign the most relevant existing label to each issue (per ' . $labelRuleReference . ')',
);

$referenceSentence = 'Apply ' . $labelRuleReference
. ' for any tracker issue this plan creates or hands off to `@skills/create-issues-from-text/SKILL.md` to create.';

$blueprint = (string) file_get_contents($packageDir . '/skills/blueprint/SKILL.md');
expect($blueprint)->toContain($referenceSentence);

$productCapability = (string) file_get_contents($packageDir . '/skills/product-capability/SKILL.md');
expect($productCapability)->toContain($referenceSentence);
});
Loading