docs(skill): expand cleveragents-contributing SKILL.md with 7 new trees and deep expansions
CI / push-validation (push) Successful in 17s
CI / helm (push) Successful in 30s
CI / lint (push) Successful in 34s
CI / typecheck (push) Successful in 49s
CI / security (push) Successful in 52s
CI / build (push) Successful in 3m20s
CI / quality (push) Successful in 3m39s
CI / integration_tests (push) Successful in 4m10s
CI / e2e_tests (push) Successful in 4m31s
CI / unit_tests (push) Successful in 5m3s
CI / docker (push) Successful in 8s
CI / coverage (push) Successful in 10m47s
CI / status-check (push) Successful in 1s
CI / benchmark-publish (push) Has been cancelled
CI / benchmark-regression (push) Has been cancelled

Add 7 new decision trees covering gaps found in CONTRIBUTING.md audit:

'Am I creating an issue?' — full issue anatomy: mandatory Metadata section
(exact commit message first line + branch name), Subtasks checkbox format
with example, Definition of Done section, label rules (State/Unverified
+Type+Priority; MoSCoW by owner only), Ref field rules, parent and blocking
link mechanics via Forgejo dependencies, bug issues companion TDD issue rule.

'Am I about to write code?' — spec-first mandate (read docs/specification.md
before any code), ADR process for architectural changes, branch must match
issue Metadata, test-first requirement, SOLID + arg validation + type
annotations requirements, prohibited list (# type: ignore, half-done work,
mocks in src/, if-testing guards).

'Am I about to commit?' — self-review diff (git add -p), atomicity rules
(one logical change, no cosmetic+functional mixing, code-move then modify),
completeness rules (tests + docs + changelog + ancillary files in same
commit), bisect-friendly / revertibility requirements, prescribed commit
first line verbatim from issue Metadata, Commitizen usage, pre-commit hook
rules, commit hygiene (topic branches, interactive rebase before merging).

'Am I submitting a PR?' — all 12 PR requirements numbered, with critical
dependency direction rule (PR→blocks→issue; reversed = deadlock with full
explanation), closing keywords, one Epic per PR, milestone + Type/ label,
after-submission state transitions, complete merge checklist.

'Am I reviewing a PR?' — eligibility and approval rules, CI gate check,
all 6 reviewer criteria (correctness, spec alignment, test quality, type
safety, readability, performance, security, style, documentation, commit
quality), requesting changes protocol, maintainer override rule.

'Am I documenting something?' — single canonical surface rule, traceability
(module.class.method + commit hash; never file:linenum), same-commit rule,
code-level docstring requirements, spec.md authority.

'Am I writing error handling?' — mandatory argument validation pattern
(before ANY other logic) with Python code example, exception propagation
rules (never suppress, never bare except, never return None on error),
fail-fast principles, AssertionError for TDD expected-fail steps.

Expand existing trees:
- 'Am I writing tests?': add multi-level testing mandate (unit + integration +
  benchmarks required for every task), what tests must cover (error paths,
  edge cases, failure modes), test failure remediation rules
- 'Which nox session?': clarify format vs format --check difference
- 'Am I looking at a CI failure?': add quality/complexity failure diagnosis,
  common causes per job type, more detail on coverage and unit_tests failures
- 'Am I writing LangChain/LangGraph code?': clarify MemorySaver requirement,
  memory class selection (Buffer vs Entity), format prohibition reasoning
- 'Which directory?': add /benchmarks/ to directory tree

Update master decision tree with 6 new branches for new trees.
Update Key Numbers table with 4 new rows.
Update frontmatter description to cover all new topics.
Override highlights table: add commit first line and PR dep direction rows.

ISSUES CLOSED: #0
This commit is contained in:
2026-04-15 19:00:54 +00:00
parent 82471f87f0
commit 38a2773261
@@ -16,21 +16,35 @@ description: |
go in, exactly which nox sessions to run, which test framework to use
(Behave for unit, Robot Framework for integration), how the TDD bug fix tag
system works with its exact validation rules, what all CI jobs are and which
are required for merge, how the v3 vs legacy CLI plan workflow differs and
why they cannot be mixed, how LangChain/LangGraph code should be structured
and tested, what the Python import rules are, what the exact backwards
compatibility policy is (none before v3.0.0), what the project's directory
layout is, or any other project-specific question.
are required for merge, how to create a well-formed issue (Metadata, Subtasks,
Definition of Done), how commits must be structured and what the commit
message first line rule is, how PRs must be submitted and what the dependency
direction rule is, how to write code spec-first with argument validation,
how documentation traceability works (module path not line number), how
the v3 vs legacy CLI plan workflow differs and why they cannot be mixed,
how LangChain/LangGraph code should be structured and tested, what the
Python import rules are, what the exact backwards compatibility policy is
(none before v3.0.0), what the project's directory layout is, or any other
project-specific question.
Covers: exact directory layout (src/cleveragents, features/, features/mocks/,
robot/, docs/, config/, scripts/, examples/, k8s/), Behave BDD unit testing
with exact step-file naming rules, Robot Framework integration testing, full
TDD bug fix workflow with three-tag system and AssertionError enforcement, all
nox sessions (unit_tests, integration_tests, e2e_tests, coverage_report,
lint, typecheck, security_scan, dead_code, complexity, benchmark,
benchmark_regression, docs, build, format), 97% coverage as hard merge gate
(measured by Slipcover via nox -s coverage_report), Pyright strict type
checking (no # type: ignore ever), Python import rules (top of file,
robot/, docs/, config/, scripts/, examples/, k8s/, benchmarks/), issue anatomy
(Metadata section, Subtasks checklist, Definition of Done, label rules, Ref
field, parent links), commit quality rules (atomic, bisect-friendly, prescribed
first line from Metadata, interactive staging, topic branches), PR requirements
(all 12 requirements, critical dependency direction: PR blocks issue not vice
versa, one Epic per PR, milestone, Type/ label), code writing rules (spec-first,
ADR for architectural changes, argument validation first in every public method,
SOLID patterns), documentation traceability (no line numbers, module.class.method
+ commit hash, same-commit requirement, single canonical surface), Behave BDD
unit testing with exact step-file naming rules, Robot Framework integration
testing, full TDD bug fix workflow with three-tag system and AssertionError
enforcement, multi-level testing mandate (unit + integration + benchmarks for
every task), all nox sessions (unit_tests, integration_tests, e2e_tests,
coverage_report, lint, typecheck, security_scan, dead_code, complexity,
benchmark, benchmark_regression, docs, build, format), 97% coverage as hard
merge gate (measured by Slipcover via nox -s coverage_report), Pyright strict
type checking (no # type: ignore ever), Python import rules (top of file,
if TYPE_CHECKING: exception), mock placement (features/mocks/ only), all 13
CI/CD jobs and 3 workflow files with triggers, 5 required-for-merge checks,
LangChain/LangGraph patterns (TypedDict state, MemorySaver, BaseLanguageModel,
@@ -94,6 +108,9 @@ nox -s build # wheel distribution build
scripts/setup-dev.sh # install pre-commit hooks — run once after cloning
hatch env create # create the Hatch project environment
# ── Commit helper ────────────────────────────────────────────────────────────
git cz # Commitizen guided commit (replaces git commit)
# ── CLI workflow (v3 — always use this, never legacy) ────────────────────────
agents plan use local/<action> <project> # create a v3 plan → returns ULID
agents plan execute <ULID> # execute the plan
@@ -130,6 +147,8 @@ They apply immediately and without negotiation:
| Benchmarks | Language benchmark tool | **ASV** (`nox -s benchmark`) |
| Backwards compat | Check project policy | **NONE before v3.0.0; begins at v3.0.0** |
| PR approvals | 1 (self-approval OK) | Same — **1 minimum, self-approval permitted** |
| Commit first line | Conventional Changelog format | **Verbatim from issue Metadata section when prescribed** |
| PR dep direction | PR blocks issue | Same — **critical: PR→blocks→issue, NEVER reversed** |
---
@@ -138,13 +157,28 @@ They apply immediately and without negotiation:
```
What am I doing?
├─ Creating or updating an issue / ticket
│ └─ → "Am I creating an issue?" tree
├─ About to start writing code
│ └─ → "Am I about to write code?" tree
├─ About to make a commit
│ └─ → "Am I about to commit?" tree
├─ Submitting a Pull Request
│ └─ → "Am I submitting a PR?" tree
├─ Reviewing someone else's PR
│ └─ → "Am I reviewing a PR?" tree
├─ Writing or placing a file
│ └─ → "Which directory does this file go in?" tree
├─ Writing tests
│ ├─ Unit-level behavior test → Behave (.feature + steps) in features/
│ ├─ Unit-level behavior → Behave (.feature + steps) in features/
│ ├─ Integration test → Robot Framework in robot/
│ ├─ End-to-end test → Robot Framework in robot/ (needs real LLM keys)
│ ├─ End-to-end → Robot Framework in robot/ (needs real LLM keys)
│ └─ → "Am I writing tests?" tree
├─ Fixing a bug
@@ -159,6 +193,9 @@ What am I doing?
├─ Looking at a CI failure
│ └─ → "Am I looking at a CI failure?" tree
├─ Writing or updating documentation
│ └─ → "Am I documenting something?" tree
├─ Working with the plan CLI
│ └─ → "Am I using the plan CLI?" tree
@@ -168,7 +205,10 @@ What am I doing?
├─ Writing Python imports
│ └─ → "Am I writing Python imports?" tree
├─ Setting up development environment
├─ Handling errors or exceptions in code
│ └─ → "Am I writing error handling?" tree
├─ Setting up the development environment
│ └─ → "Am I setting up my development environment?" tree
├─ Releasing a new version
@@ -182,6 +222,420 @@ What am I doing?
## 🔄 Project-Specific Decision Trees
### "Am I creating an issue?"
```
Issue creation — complete requirements:
├─ BEFORE CREATING: does a similar issue already exist?
│ ├─ YES → add context to the existing issue; do NOT create a duplicate
│ └─ NO → continue
├─ TITLE
│ ├─ Specific and descriptive — reader should understand scope from title alone
│ ├─ e.g. "Fix null pointer when parsing empty configuration file"
│ └─ ⚠️ NEVER vague: not "Fix bug", "Improve performance", "Update tests"
├─ MANDATORY LABELS (set at creation)
│ ├─ State/Unverified ← ALL new issues start here, no exceptions
│ ├─ Type/ label ← exactly one (Bug, Feature, Task, Testing, Epic, Legendary)
│ └─ Priority/ label ← suggest Priority/Backlog if unsure; maintainer adjusts
│ ⚠️ DO NOT set MoSCoW/ labels — project owner ONLY sets these
├─ MILESTONE
│ ├─ At creation (State/Unverified): optional
│ └─ Once in any active state (Verified, In progress, etc.): MANDATORY
│ If no appropriate milestone exists → discuss with project owner first
├─ BRANCH/TAG REF FIELD (the "Ref" field on the issue form)
│ ├─ Development issues (feature, fix, chore, refactor — has a branch):
│ │ → Must be set to the SAME branch named in the Metadata section
│ │ → Required once issue moves to State/In progress or later
│ │ → Must reference a BRANCH, never a tag
│ └─ Non-development issues (bug reports, questions, support):
│ → May be left blank, or set to the branch/tag where the issue occurs
├─ DESCRIPTION — MANDATORY SECTIONS (in this order)
│ │
│ ├─ ## Metadata ← MUST be at the top
│ │ ├─ Commit Message: feat(scope): exact first line for the commit
│ │ │ e.g. feat(cli): add tool and validation commands
│ │ │ → This exact text will be the commit message first line
│ │ │ → Must follow Conventional Changelog format
│ │ └─ Branch: feature/m3-tool-cli
│ │ → This exact branch name will be used for all work on this issue
│ │
│ ├─ Background and context
│ │ → Why does this issue exist? What is the motivation?
│ │
│ ├─ Current behavior (for bugs: repro steps, error messages, logs)
│ │ → What is happening now that is incorrect or undesirable?
│ │
│ ├─ Expected behavior
│ │ → What should happen instead, or what does "done" look like?
│ │
│ ├─ Acceptance criteria
│ │ → Testable list of conditions — each one binary (either passes or not)
│ │ → Any reviewer can independently verify each criterion
│ │
│ ├─ Supporting information
│ │ → Links to related issues, docs, screenshots, logs, external references
│ │
│ ├─ ## Subtasks ← REQUIRED (except trivially simple single-line changes)
│ │ ├─ Each subtask is a checkbox: - [ ] description
│ │ ├─ Break work into discrete, trackable steps
│ │ └─ Example:
│ │ - [ ] Implement input validation for configuration parser
│ │ - [ ] Add error messages for malformed YAML files
│ │ - [ ] Tests (Behave): Add scenarios for config parsing edge cases
│ │ - [ ] Tests (Robot): Add integration test for config loading
│ │ - [ ] Verify coverage >=97% via nox -s coverage_report
│ │ - [ ] Run nox (all default sessions), fix any errors
│ │
│ └─ ## Definition of Done ← REQUIRED
│ └─ Example:
│ This issue is complete when:
│ - All subtasks above are completed and checked off.
│ - A Git commit is created where the first line of the commit message
│ matches the Commit Message in Metadata exactly, followed by a blank
│ line and then additional implementation details.
│ - The commit is pushed to the remote on the branch matching the
│ Branch in Metadata exactly.
│ - The commit is submitted as a pull request to master, reviewed,
│ and merged before this issue is marked done.
├─ PARENT LINK (hierarchy)
│ ├─ If this is a child of an Epic or Legendary:
│ │ → Open the child issue → add parent under "blocks"
│ │ OR open the parent → add child under "depends on"
│ └─ ⚠️ NEVER reference parent tickets by number in the description body
│ The machine-readable Forgejo dependency link is the ONLY mechanism
├─ BLOCKING LINKS
│ ├─ If this issue is blocked by another issue:
│ │ 1. Add Blocked label
│ │ 2. Comment: "Blocked by #57"
│ │ 3. Add Forgejo dependency: blocking issue BLOCKS this issue
│ │ 4. If no ticket exists for the blocker → create one first
│ │ 5. Move to State/Paused
│ └─ When blocker resolves → remove Blocked label → return to State/In progress
├─ SPECIAL CASE: Bug issue (Type/Bug)
│ ├─ Priority is ALWAYS Priority/Critical — no exceptions
│ ├─ MoSCoW is ALWAYS MoSCoW/Must Have — project owner sets this
│ ├─ You MUST also immediately create a companion Type/Testing issue:
│ │ ├─ Title: "TDD: <exact description from the bug issue>"
│ │ ├─ Same Priority/Critical + MoSCoW/Must Have
│ │ └─ Set Forgejo dependency: Bug issue DEPENDS ON the TDD issue
│ └─ See "Am I fixing a bug? (TDD workflow)" for the full process
└─ AFTER CREATING
└─ The issue starts in State/Unverified — a maintainer triages it
Contributors do NOT move their own issues out of State/Unverified
```
### "Am I about to write code?"
```
Before touching any production code:
├─ STEP 1: READ docs/specification.md FIRST (mandatory)
│ ├─ Find the sections relevant to your task
│ ├─ Read them completely — understand the intended design
│ ├─ If the spec and the current codebase disagree:
│ │ → The SPEC is correct. Align the code to the spec.
│ │ → NEVER adjust the spec to match broken code
│ └─ Architectural changes → ADR process required BEFORE writing any code
│ 1. Capture proposed change in an ADR document
│ 2. Submit for review and approval
│ 3. Once approved → update docs/specification.md
│ 4. THEN write the code
├─ STEP 2: Does a verified issue exist for this work?
│ ├─ NO → Create the issue first (see "Am I creating an issue?" tree)
│ └─ YES → Is it in State/Verified?
│ ├─ State/Unverified → wait for triage; do NOT start
│ └─ State/Verified → move to State/In progress and assign yourself
├─ STEP 3: Are you on the correct topic branch?
│ ├─ Branch name must match the Branch field in the issue Metadata section
│ ├─ Format: feature/mN-<name>, bugfix/mN-<name>, or tdd/mN-<name>
│ └─ If the branch doesn't exist yet → create it from master
├─ STEP 4: Do tests exist for the new behavior FIRST?
│ └─ Write tests BEFORE writing implementation — no exceptions
│ (See "Am I writing tests?" for the multi-level testing mandate)
├─ CODE STYLE REQUIREMENTS (apply while writing)
│ ├─ Files under 500 lines — break into focused modules if approaching limit
│ ├─ Every public/protected method validates ALL arguments first, before logic
│ │ (See "Am I writing error handling?" for the exact validation pattern)
│ ├─ Type annotations on every function signature, variable, and return type
│ ├─ Never hardcode secrets, tokens, API keys, or environment-specific values
│ ├─ Use SOLID principles throughout (SRP, OCP, LSP, ISP, DIP)
│ ├─ Prefer design patterns over ad-hoc solutions (see references/toolchain/)
│ └─ Use dependency injection — do not create dependencies internally
├─ WHAT IS PROHIBITED
│ ├─ ⚠️ No half-done work — only commit when fully implemented and tested
│ ├─ ⚠️ No debug statements in committed code
│ ├─ ⚠️ No # type: ignore comments anywhere
│ ├─ ⚠️ No hardcoded secrets or credentials
│ ├─ ⚠️ No production code in test directories (src/ is production only)
│ ├─ ⚠️ No test or mock code in src/cleveragents/
│ └─ ⚠️ No if testing: guards or test-only paths in production code
└─ BEFORE STOPPING FOR THE DAY
├─ Use feature branches and stashing for work in progress
├─ NEVER commit incomplete or untested code
└─ Use git stash or draft commits on your branch — not main history
```
### "Am I about to commit?"
```
Commit quality checklist — every single commit:
├─ IS THE WORK COMPLETE AND TESTED?
│ ├─ Feature or fix fully implemented?
│ ├─ All new behavior covered by tests?
│ ├─ nox → all sessions green? (run it now if not)
│ ├─ nox -s coverage_report → still ≥ 97%?
│ └─ ⚠️ If any of the above is NO → do NOT commit yet
├─ SELF-REVIEW THE DIFF (mandatory before every commit)
│ ├─ git add -p → use interactive staging to select only intended changes
│ ├─ git diff --staged → review exactly what will be committed
│ ├─ Are there debug statements? Remove them.
│ ├─ Are there temporary comments? Remove them.
│ ├─ Are there unrelated changes? Unstage them — separate commit.
│ └─ Are there cosmetic changes mixed with functional changes?
│ → Separate them into distinct commits
├─ IS THIS COMMIT ATOMIC?
│ ├─ One logical change only — one bug fix OR one feature OR one refactor
│ ├─ If it requires "and" to describe → split it into two commits
│ ├─ Related edits across multiple files → OK in one commit
│ ├─ Unrelated edits that happen to touch the same file → split
│ ├─ Code move/rename → one commit; modifications → next commit
│ └─ Never bundle formatting fixes with functional changes
├─ IS THE COMMIT COMPLETE? (everything that belongs together goes together)
│ ├─ Tests for this change included in this same commit?
│ ├─ Documentation updated for this change in this same commit?
│ ├─ Changelog updated in this same commit (one entry)?
│ ├─ Ancillary files updated (config, build scripts, etc.)?
│ └─ ⚠️ "I'll add tests later" is never acceptable
├─ IS THE COMMIT INDEPENDENTLY BUILDABLE AND REVERTIBLE?
│ ├─ If someone checks out ONLY this commit: does the project build?
│ ├─ If someone checks out ONLY this commit: do all tests pass?
│ ├─ If this commit is reverted: does the codebase still make sense?
│ ├─ Does this commit secretly depend on a FUTURE commit to work?
│ │ → That is a bug in your commit strategy — fix it
│ └─ Keep history bisect-friendly: every commit is a valid testable state
├─ COMMIT MESSAGE FIRST LINE (critical)
│ │
│ ├─ DOES THE ISSUE HAVE A Metadata section with a Commit Message field?
│ │ ├─ YES → Use that text EXACTLY as the first line — verbatim, copy-paste
│ │ │ → Do NOT paraphrase, reword, or reformat it
│ │ │ → e.g. feat(cli): add tool and validation commands
│ │ └─ NO → Write your own following Conventional Changelog format:
│ │ <type>(<scope>): <description in imperative mood>
│ │ Types: feat, fix, docs, style, refactor, test, chore, perf, ci, build, revert
│ │ 50-72 characters max, no period at end
│ │
│ ├─ COMMIT BODY (free-form, after a blank line)
│ │ ├─ Explain WHAT was done and WHY (not how — the diff shows how)
│ │ ├─ Include trade-offs, rationale, and relevant context
│ │ └─ Footer: ISSUES CLOSED: #N (or Refs: #N if not closing)
│ │
│ └─ USE COMMITIZEN (strongly recommended):
│ git cz → interactive guided message creation
├─ PRE-COMMIT HOOKS (automatic when setup-dev.sh was run)
│ ├─ Hooks run automatically on git commit — they enforce quality locally
│ ├─ Format, lint, typecheck, security scan, commit message validation
│ ├─ If a hook fails → fix the issue; NEVER use --no-verify to bypass
│ └─ If hooks are not installed → run scripts/setup-dev.sh first
└─ COMMIT HYGIENE
├─ Commit often — small commits are easier to review and revert
├─ Use topic branches — develop on a branch, never directly on master
├─ Clean up history before merging:
│ → Use interactive rebase to fix typos, squash fixup commits
│ → Every commit in the PR should be meaningful and clean
└─ Reference issues in every commit footer (ISSUES CLOSED: #N)
```
### "Am I submitting a Pull Request?"
```
Pull Request requirements — ALL must be satisfied before review:
├─ PRE-SUBMISSION CHECKLIST (12 items — PR will not be reviewed until all pass)
│ │
│ ├─ 1. DETAILED DESCRIPTION
│ │ ├─ Summary of changes and the motivation behind them
│ │ ├─ Closing keyword for every linked issue: Closes #N or Fixes #N
│ │ │ (PR without issue reference will NOT be reviewed)
│ │ └─ Create an issue first if none exists — see "Am I creating an issue?"
│ │
│ ├─ 2. FORGEJO DEPENDENCY DIRECTION (CRITICAL — deadlock risk if wrong)
│ │ ├─ On the PR: add the linked issue under "blocks"
│ │ ├─ Result: on the issue, the PR appears under "depends on"
│ │ ├─ ⚠️ CORRECT: PR → blocks → issue
│ │ ├─ ⚠️ WRONG: issue → blocks → PR ← this creates a deadlock
│ │ │ If reversed, Forgejo prevents the PR from being merged or closed
│ │ │ until the issue resolves first — but the issue can't close until
│ │ │ the PR merges → UNRESOLVABLE. Always verify before saving.
│ │ └─ Verify: open the issue, confirm PR appears under "depends on"
│ │
│ ├─ 3. ONE EPIC SCOPE PER PR
│ │ ├─ Each PR is associated with exactly one Epic
│ │ └─ Changes spanning multiple Epics → split into separate PRs
│ │
│ ├─ 4. ATOMIC, WELL-SCOPED COMMITS
│ │ ├─ All commits follow commit quality rules (see "Am I about to commit?")
│ │ └─ Each commit is small, self-contained, independently buildable
│ │
│ ├─ 5. COMMIT MESSAGES REFERENCE TICKETS
│ │ └─ Every commit footer includes ISSUES CLOSED: #N or Refs: #N
│ │
│ ├─ 6. CONVENTIONAL CHANGELOG FORMAT
│ │ └─ All commit messages follow type(scope): description format
│ │
│ ├─ 7. CHANGELOG UPDATED
│ │ └─ One new entry per commit, describing the change for users
│ │
│ ├─ 8. NO BUILD OR INSTALL ARTIFACTS
│ │ └─ No compiled outputs, .egg-info, __pycache__, dist/ in any commit
│ │
│ ├─ 9. CONTRIBUTORS.md UPDATED
│ │ └─ Add your name if not already listed (first contribution only)
│ │
│ ├─ 10. VERSION BUMP (when warranted)
│ │ ├─ New functionality → bump MINOR in pyproject.toml
│ │ ├─ Bug fix in released version → bump PATCH
│ │ ├─ Breaking API change → bump MAJOR
│ │ └─ Refactor / docs / tests → usually NO bump needed
│ │
│ ├─ 11. ALL CI CHECKS PASS
│ │ ├─ Run nox locally — full suite must be green
│ │ └─ PRs with failing CI will NOT be reviewed
│ │
│ └─ 12. MILESTONE AND TYPE LABEL
│ ├─ Assigned to the same milestone as the linked issue(s)
│ │ (if issues span milestones → use the primary issue's milestone)
│ └─ Exactly one Type/ label: Type/Bug, Type/Feature, or Type/Task
├─ AFTER SUBMISSION
│ ├─ Move linked issue(s) to State/In review
│ ├─ Watch CI — fix failures immediately; do not leave broken PRs waiting
│ ├─ Respond to review comments constructively
│ ├─ Push updated commits to address requested changes
│ └─ After merge → move linked issue(s) to State/Completed
└─ MERGE REQUIREMENTS (ALL conditions before merging)
├─ PR description includes closing keywords (Closes #N)
├─ Forgejo dependency direction correct: PR blocks issue
├─ All CI checks pass (lint, typecheck, security, unit_tests, coverage)
├─ Coverage ≥ 97%
├─ At least 1 approving review (formal APPROVED or LGTM/✅; self-approval OK)
├─ No open "Request Changes" or "Rejected" reviews
├─ All commits follow Conventional Changelog format
├─ Every commit references its issue
├─ Changelog updated
├─ CONTRIBUTORS.md updated (if applicable)
├─ Correct milestone assigned
└─ Exactly one Type/ label applied
```
### "Am I reviewing a PR?"
```
Code review — what to assess and how to decide:
├─ ELIGIBILITY AND APPROVAL RULES
│ ├─ Anyone may review any PR
│ ├─ Minimum 1 approving review required before merge
│ ├─ Self-approval IS permitted (including bot PRs)
│ ├─ Valid approval = formal "APPROVED" status OR comment with LGTM/✅/Approved
│ └─ No open "Request Changes" reviews at merge time
├─ CI GATE (check this first — do not review if CI is red)
│ ├─ All required jobs must be green: lint, typecheck, security, unit_tests, coverage
│ ├─ status-check job provides consolidated summary
│ └─ If CI is failing → ask the author to fix it before reviewing
├─ WHAT TO EVALUATE (in order of importance)
│ │
│ ├─ CORRECTNESS
│ │ ├─ Does it do what the linked issue says it should do?
│ │ ├─ Do all acceptance criteria in the issue pass?
│ │ └─ Are there edge cases not covered that could cause failures?
│ │
│ ├─ SPECIFICATION ALIGNMENT
│ │ ├─ Does it align with docs/specification.md?
│ │ └─ If code departs from spec → it is wrong; ask for correction
│ │
│ ├─ TEST QUALITY
│ │ ├─ Are there Behave BDD scenarios for all new behavior?
│ │ ├─ Are integration tests updated if component interfaces changed?
│ │ ├─ Are edge cases and error/failure paths covered?
│ │ ├─ Does coverage stay ≥ 97%?
│ │ └─ For bug fixes: does a @tdd_issue_N regression test exist?
│ │
│ ├─ TYPE SAFETY
│ │ ├─ Are all function signatures, variables, and return types annotated?
│ │ └─ ⚠️ Zero tolerance for # type: ignore — reject any PR that adds one
│ │
│ ├─ READABILITY
│ │ ├─ Clear, descriptive names for classes, functions, variables?
│ │ ├─ No magic numbers or unexplained constants?
│ │ └─ Easy to follow logic without reading the whole file?
│ │
│ ├─ PERFORMANCE
│ │ ├─ Unnecessary inefficiencies or redundant operations?
│ │ ├─ N+1 query patterns in loops?
│ │ └─ Potential scalability concerns?
│ │
│ ├─ SECURITY
│ │ ├─ Any hardcoded secrets, tokens, or credentials?
│ │ ├─ SQL/command injection, path traversal, or unsafe patterns?
│ │ └─ Validate all inputs from external sources?
│ │
│ ├─ CODE STYLE
│ │ ├─ SOLID principles followed?
│ │ ├─ Appropriate design patterns used?
│ │ ├─ Files under 500 lines?
│ │ └─ Follows ruff conventions (already enforced by lint CI job)?
│ │
│ ├─ DOCUMENTATION
│ │ ├─ All public functions/classes have docstrings?
│ │ └─ Documentation updated alongside code in the same commit?
│ │
│ └─ COMMIT AND PR QUALITY
│ ├─ Each commit atomic and self-contained?
│ ├─ Commit message first lines follow Conventional Changelog?
│ │ (or match the prescribed text from the issue Metadata section)
│ ├─ Each commit footer has ISSUES CLOSED: #N?
│ ├─ Changelog updated with one entry per commit?
│ ├─ Dependency direction correct: PR blocks issue?
│ ├─ Correct milestone assigned?
│ └─ Exactly one Type/ label?
├─ WHEN REQUESTING CHANGES
│ ├─ Be specific and constructive — explain WHY, suggest HOW
│ ├─ Document all findings in the PR discussion thread
│ └─ Author must address every comment before re-review
└─ MAINTAINER OVERRIDE
└─ Project owner may merge with fewer requirements in urgent situations
(this is rare and the exception, not the norm)
```
### "Which directory does this file go in?"
```
@@ -209,6 +663,10 @@ File placement rules for this project (every path is exact — no variations):
│ ├─ .robot files and .resource files
│ └─ ⚠️ No mocks allowed here — real services ONLY
├─ Is this a PERFORMANCE BENCHMARK?
│ └─ → /benchmarks/
│ └─ ASV (Airspeed Velocity) benchmark files
├─ Is this DOCUMENTATION?
│ └─ → /docs/
│ ├─ Must be written in MkDocs-compatible markdown
@@ -244,20 +702,35 @@ File placement rules for this project (every path is exact — no variations):
### "Am I writing tests?"
```
Testing rules for this project:
Testing rules and multi-level mandate for this project:
├─ MULTI-LEVEL TESTING MANDATE (applies to every coding task)
│ ├─ Every task MUST include or update tests at ALL of these levels:
│ │ ├─ 1. Unit tests (Behave BDD scenarios)
│ │ ├─ 2. Integration tests (Robot Framework)
│ │ └─ 3. Performance benchmarks (ASV) — for performance-sensitive code
│ ├─ Testing is NON-OPTIONAL — it is part of the definition of done
│ └─ Work is NOT done until all three levels are addressed
├─ WHICH FRAMEWORK DO I USE?
│ ├─ Unit-level behavior → Behave (Cucumber/Gherkin)
│ │ ├─ Feature files: features/*.feature or features/<topic>/*.feature
│ │ ├─ Step definitions: features/steps/<name>_steps.py
│ │ └─ Run: nox -s unit_tests
│ ├─ Integration test (real services) → Robot Framework
│ ├─ Integration test (real services, no mocks) → Robot Framework
│ │ ├─ Location: robot/*.robot or robot/<topic>/*.robot
│ │ └─ Run: nox -s integration_tests
│ └─ End-to-end test (real LLM keys required) → Robot Framework
│ ├─ Location: robot/*.robot (e2e-tagged or e2e subdirectory)
│ └─ Run: nox -s e2e_tests
├─ WHAT TESTS MUST COVER
│ ├─ Normal operation (the happy path)
│ ├─ All error and exception paths
│ ├─ Edge cases and boundary conditions
│ ├─ Failure modes that could occur in production
│ └─ Every new behavior introduced — not just line coverage
├─ WHAT AM I PROHIBITED FROM DOING?
│ ├─ ⚠️ NO pytest-style unit tests — ever
│ ├─ ⚠️ NO tests/ directory — it intentionally does not exist
@@ -285,8 +758,17 @@ Testing rules for this project:
│ ├─ Exception: project owner can grant a documented exception
│ └─ Any exclusion from coverage: explicit project owner approval required
├─ TEST FAILURE REMEDIATION
│ ├─ Any test failure during development → immediately becomes blocking task
│ ├─ Document the failure context
│ ├─ Resolve it BEFORE progressing to other work
│ ├─ Exception: @tdd_expected_fail tests are tracked failures (not unaddressed)
│ │ → they are resolved through the TDD bug fix workflow
│ └─ Never leave a known-failing test unaddressed
├─ PERFORMANCE BENCHMARKS
│ ├─ Include ASV benchmarks for performance-sensitive code
│ ├─ Write ASV benchmarks for all performance-sensitive code
│ ├─ Location: benchmarks/
│ ├─ Run: nox -s benchmark
│ └─ PRs: regression check via nox -s benchmark_regression
@@ -434,7 +916,7 @@ Exact TDD tag rules (all enforced by CI hooks):
```
Complete nox session reference for this project:
├─ BEFORE EVERY COMMIT (all four must be green):
├─ BEFORE EVERY COMMIT (all must be green):
│ ├─ nox -s lint # ruff linting + format check
│ ├─ nox -s typecheck # Pyright strict (zero suppressions)
│ ├─ nox -s unit_tests # Behave BDD scenarios
@@ -446,21 +928,24 @@ Complete nox session reference for this project:
│ ├─ nox -s dead_code # vulture unused code detection
│ └─ nox -s integration_tests # Robot Framework (parallel via pabot)
├─ SESSION REFERENCE:
│ ├─ nox -s lint # ruff linting + format check
│ ├─ nox -s format # auto-format code with ruff
│ ├─ nox -s format -- --check # format check only (CI mode, no changes)
├─ SESSION REFERENCE (what each session does):
│ ├─ nox -s lint # ruff: find linting violations + check formatting
│ ├─ nox -s format # ruff: AUTO-FIX formatting (modifies files)
│ ├─ nox -s format -- --check # ruff: check formatting ONLY, no changes (CI mode)
│ │ ⚠️ format and format --check are different:
│ │ → format: changes your files (run locally to fix)
│ │ → format --check: reports violations without changing (CI uses this)
│ ├─ nox -s typecheck # Pyright strict type checking
│ ├─ nox -s security_scan # bandit + semgrep + vulture
│ ├─ nox -s dead_code # vulture dead code detection
│ ├─ nox -s complexity # Radon complexity (nightly quality sweep)
│ ├─ nox -s unit_tests # Behave BDD tests
│ ├─ nox -s integration_tests # Robot Framework integration tests
│ ├─ nox -s unit_tests # Behave BDD tests (features/)
│ ├─ nox -s integration_tests # Robot Framework integration tests (robot/)
│ ├─ nox -s e2e_tests # Robot Framework e2e (real LLM keys required)
│ ├─ nox -s coverage_report # Slipcover coverage (fail-under 97%)
│ ├─ nox -s benchmark # ASV performance benchmarks
│ ├─ nox -s benchmark_regression# ASV benchmark regression (PRs only)
│ ├─ nox -s docs # MkDocs build
│ ├─ nox -s docs # MkDocs documentation build
│ └─ nox -s build # wheel distribution build
├─ CI JOB → SESSION MAPPING:
@@ -508,50 +993,122 @@ Diagnosing CI failures in this project:
├─ DIAGNOSING EACH FAILURE:
│ │
│ ├─ lint failure
│ │ ├─ Run locally: nox -s lint → see exact violations
│ │ ├─ Auto-fix: nox -s format (modifies files)
│ │ ─ Remaining violations → fix manually, then re-run
│ │ ├─ Run locally: nox -s lint → see exact violations with line references
│ │ ├─ Auto-fix formatting: nox -s format (modifies files)
│ │ ─ Remaining violations after auto-fix → fix manually, then re-run
│ │ └─ Common causes: unused imports, line length, style violations
│ │
│ ├─ typecheck failure
│ │ ├─ Run locally: nox -s typecheck → see Pyright errors
│ │ ├─ Run locally: nox -s typecheck → see Pyright errors with context
│ │ ├─ Fix ALL type errors — every single one
│ │ ├─ ⚠️ NEVER add # type: ignore — this is prohibited unconditionally
│ │ ─ ⚠️ NEVER disable Pyright in pyproject.toml or noxfile.py
│ │ ─ ⚠️ NEVER disable Pyright in pyproject.toml or noxfile.py
│ │ └─ Common causes: missing annotations, wrong return types, None handling
│ │
│ ├─ security failure
│ │ ├─ Run: nox -s security_scan → bandit + semgrep findings
│ │ ├─ Run: nox -s dead_code → vulture findings
│ │ ├─ High-severity bandit findings → must be fixed, not suppressed
│ │ Suppress findings only with proper justification inline comment
│ │ Low-severity bandit findings → suppress ONLY with justification comment
│ │ └─ Dead code → remove it or document why it must remain
│ │
│ ├─ unit_tests failure
│ │ ├─ Run: nox -s unit_tests → see failing Behave scenarios
│ │ ├─ Fix the failing step definition or the production code it tests
│ │ ⚠️ @tdd_expected_fail failure = bug was fixed WITHOUT removing tag
│ │ → remove @tdd_expected_fail from the scenario, re-run
│ │ ├─ Run: nox -s unit_tests → see failing Behave scenarios with context
│ │ ├─ Read the failing scenario and step output carefully
│ │ Fix the failing step definition or the production code it exercises
│ │ ├─ ⚠️ @tdd_expected_fail failure = bug was fixed WITHOUT removing the tag
│ │ │ → remove @tdd_expected_fail from the scenario, re-run
│ │ └─ ⚠️ "Step not found" error = placeholder step was committed → implement it
│ │
│ ├─ coverage failure
│ │ ├─ Run: nox -s coverage_report → see COVERAGE OK / COVERAGE FAILED
│ │ ├─ Find uncovered lines in coverage report
│ │ ├─ Add Behave scenarios or Robot tests for uncovered paths
│ │ ├─ Run: nox -s coverage_report → look for COVERAGE OK / COVERAGE FAILED
│ │ ├─ Open the coverage HTML report to find specific uncovered lines
│ │ ├─ Add Behave scenarios or Robot tests for the uncovered paths
│ │ ├─ Focus on untested error paths, edge cases, and branches
│ │ └─ Exclusions require explicit project owner approval
│ │
│ ├─ TDD tag gate failure
│ │ ├─ "@tdd_expected_fail still present on @tdd_issue_N" →
│ │ │ remove @tdd_expected_fail tag from the scenario
│ │ │ remove @tdd_expected_fail from the scenario
│ │ └─ "no @tdd_issue_N test found for bug #N" →
│ │ TDD step was skipped; must write the TDD test first
│ │
│ ├─ quality failure (Radon complexity — informational, runs nightly)
│ │ ├─ Run: nox -s complexity → see complex functions/methods
│ │ ├─ Refactor functions with high complexity (cyclomatic complexity > 10)
│ │ └─ Break large functions into smaller, focused ones
│ │
│ └─ benchmark-regression failure (informational, not blocking)
│ ├─ Check artifact uploaded by the benchmark-regression job
Investigate which benchmark regressed and why
│ ├─ Check the artifact uploaded by the benchmark-regression job
Download and inspect the ASV comparison report
│ └─ Investigate which benchmark regressed and whether it matters
└─ AFTER FIXING
├─ Run affected nox session locally to confirm fix
├─ Run the affected nox session locally to confirm the fix
├─ Run nox (full suite) to ensure no regressions introduced
└─ Push — CI re-runs automatically on the new commit
```
### "Am I documenting something?"
```
Documentation standards for this project:
├─ WHERE DOES DOCUMENTATION LIVE?
│ ├─ Architecture and design decisions → docs/specification.md
│ │ (modify only via ADR process — see "Am I about to write code?" tree)
│ ├─ User-facing guides, API docs, how-tos → docs/ (MkDocs format)
│ ├─ Code documentation → docstrings/inline comments in source files
│ └─ Change history → CHANGELOG (one entry per commit, user perspective)
├─ SINGLE CANONICAL SURFACE (mandatory)
│ ├─ Each type of documentation has exactly ONE home
│ ├─ Do NOT scatter related notes across multiple files
│ ├─ If a doc already exists for this purpose → UPDATE it, don't create parallel
│ └─ If multiple sources of truth exist → consolidate them into one
├─ TRACEABILITY RULES (strictly enforced)
│ ├─ Reference code by LOGICAL LOCATION — never by line number
│ │ ├─ ⚠️ NEVER: mypackage/services.py:142 ← line numbers shift constantly
│ │ ├─ CORRECT format: module.class.method
│ │ │ e.g. cleveragents.services.plan_service.PlanService.execute
│ │ └─ Why: line numbers become misleading with every edit
│ ├─ Include the commit hash at time of writing
│ │ └─ e.g. "At commit a3f92b1, PlanService.execute was refactored to..."
│ │ → If names are later refactored, the commit hash traces the original
│ └─ Record substantive design decisions alongside the logical code references
├─ CONTINUOUS DOCUMENTATION (same-commit rule)
│ ├─ Documentation changes go in the SAME commit as the code they document
│ ├─ ⚠️ "I'll document it later" is never acceptable
│ ├─ If you discovered something during implementation → document it immediately
│ └─ Work is NOT done until all affected documentation is updated
├─ CODE-LEVEL DOCUMENTATION
│ ├─ All public classes → class-level docstring explaining purpose and usage
│ ├─ All public methods and functions → docstring with:
│ │ ├─ What the method does (purpose)
│ │ ├─ Args (name, type, description)
│ │ ├─ Returns (type, description)
│ │ └─ Raises (exception types and when)
│ ├─ Non-obvious logic → inline comment explaining WHY (not WHAT)
│ │ e.g. # must copy here — caller holds a reference to original
│ └─ Never write comments that merely restate the code:
│ ⚠️ WRONG: x = x + 1 # increment x
│ ✓ RIGHT: x = x + 1 # offset by one to skip the sentinel value
├─ DOCS/SPECIFICATION.MD (the most important doc)
│ ├─ Read this BEFORE starting any task — especially the relevant sections
│ ├─ When code and spec disagree → code is wrong; align code to spec
│ ├─ Proposing a spec change → ADR process required first
│ └─ Never edit to reflect incorrect code — only to reflect approved decisions
└─ MKDOCS DOCUMENTATION (docs/)
├─ All markdown in docs/ must be valid MkDocs-compatible format
├─ Build and preview locally: nox -s docs
└─ API docs, user guides, architecture overviews all live here
```
### "Am I using the plan CLI?"
```
@@ -609,15 +1166,20 @@ LangChain/LangGraph design and implementation rules:
│ ├─ Node naming: descriptive verb-based names
│ │ e.g. analyze_requirements, generate_plan, validate_output
│ ├─ Checkpointing: ALWAYS integrate MemorySaver for workflow resumption
│ │ → Compile EVERY graph with checkpointer=MemorySaver()
│ │ → Never omit for graphs with more than one execution step
│ └─ Conditional edges: clear decision functions with descriptive names
├─ LANGCHAIN INTEGRATION
│ ├─ Provider abstraction: ALWAYS use BaseLanguageModel or BaseLLM
│ │ NEVER hardcode a specific provider (OpenAI, Anthropic, etc.) directly
│ ├─ All prompts via ChatPromptTemplate or PromptTemplate — never f-strings
│ │ ⚠️ f-strings as prompts are not composable, traceable, or testable
│ ├─ Implement BOTH sync (invoke) AND async (ainvoke) with streaming
│ ├─ Memory: use ConversationBufferMemory or EntityMemory as appropriate
└─ Output parsing: StrOutputParser, JsonOutputParser (structured output)
│ ├─ Memory classes:
│ ├─ ConversationBufferMemory → for conversation history across turns
│ │ └─ EntityMemory → for tracking named entities across a conversation
│ └─ Output parsing: StrOutputParser (text), JsonOutputParser (structured)
├─ CONFIGURATION
│ ├─ Environment variables: use standard LangChain env vars
@@ -651,7 +1213,7 @@ LangChain/LangGraph design and implementation rules:
└─ WHAT IS PROHIBITED
├─ Hardcoding a specific LLM provider in production code
├─ Using real LLM API calls in unit tests
├─ Using real LLM API calls in unit tests (features/)
├─ Enabling LangSmith by default
├─ Using f-strings directly as prompts (always use PromptTemplate)
└─ Missing MemorySaver in any graph that has more than one execution step
@@ -664,7 +1226,7 @@ Python-specific import rules for this project:
├─ WHERE DO IMPORTS GO?
│ ├─ ALL imports must be at the TOP of the file
│ ├─ Before: module docstring, then __all__, then imports
│ ├─ Before: module docstring __all__ imports
│ ├─ ⚠️ NEVER inside functions, methods, or class bodies
│ └─ ⚠️ NEVER inside if, try, for, while, or with blocks
@@ -683,10 +1245,65 @@ Python-specific import rules for this project:
│ └─ ⚠️ No wildcard imports: never "from module import *"
└─ ORDER (follow isort / ruff conventions, enforced by nox -s lint)
├─ Standard library imports
├─ Third-party imports
└─ Local application imports
(blank line between each group — ruff auto-enforces this)
├─ Standard library imports (e.g. import os, from typing import Any)
├─ Third-party imports (e.g. from langchain_core.llms import BaseLLM)
└─ Local application imports (e.g. from cleveragents.services import PlanService)
(blank line between each group — ruff auto-enforces and auto-fixes this)
```
### "Am I writing error handling?"
```
Error and exception handling rules for this project:
├─ ARGUMENT VALIDATION — MANDATORY IN EVERY PUBLIC/PROTECTED METHOD
│ ├─ Validate ALL arguments FIRST, before any other logic
│ ├─ This is not optional — it is enforced in code review
│ ├─ Checks to perform (in order):
│ │ ├─ Null/None checks → reject None where not expected
│ │ ├─ Type verification → prefer compile-time (Pyright) over runtime checks
│ │ │ Use runtime type checks ONLY at untyped boundaries (deserialized input,
│ │ │ dynamic plugin APIs, data from external systems)
│ │ ├─ Value range → numeric values within acceptable bounds
│ │ ├─ Empty strings → reject where non-empty is required
│ │ ├─ Empty collections → reject where elements are required
│ │ └─ Invalid states → verify object state is valid for the operation
│ └─ Example (Python):
│ def process_data(self, data: list[str], threshold: int) -> None:
│ if data is None:
│ raise ValueError("data cannot be None")
│ if not data:
│ raise ValueError("data cannot be empty")
│ if not all(isinstance(item, str) for item in data):
│ raise TypeError("data must contain only strings")
│ if threshold < 0 or threshold > 100:
│ raise ValueError(
│ f"threshold must be between 0 and 100, got {threshold}"
│ )
│ # ONLY NOW: actual business logic begins
├─ EXCEPTION PROPAGATION (critical rule)
│ ├─ Let exceptions propagate to top-level — do NOT suppress them
│ ├─ ⚠️ NEVER catch an exception just to log it and re-raise
│ │ → just let it propagate naturally
│ ├─ ⚠️ NEVER use bare except: or except Exception: without re-raising
│ │ unless you have SPECIFIC recovery logic (retry, cleanup, add context)
│ ├─ ⚠️ NEVER return None or a default value to mask an error condition
│ │ → raise an exception or return an explicit error type
│ └─ ONLY catch when you can MEANINGFULLY HANDLE (retry logic, resource
│ cleanup, adding diagnostic context before re-raising)
├─ FAIL-FAST PRINCIPLES
│ ├─ Check preconditions at function ENTRY, not deep inside logic
│ ├─ Make failure conditions explicit — never implicit or hidden
│ ├─ Use assertions for invariants that should NEVER be violated
│ └─ Benefits: bugs surface closer to their source; stack traces are meaningful
└─ TDD EXPECTED-FAIL EXCEPTION: use AssertionError ONLY
├─ In @tdd_expected_fail Behave steps:
│ → assert condition, "message" OR raise AssertionError("...")
├─ ⚠️ NOT ValueError, RuntimeError, OSError, or any other exception type
└─ The TDD hook ONLY inverts AssertionError — other exceptions break CI
```
### "Am I setting up my development environment?"
@@ -798,6 +1415,7 @@ Release process for this project:
| Unit test directory | **`/features/`** | Behave only — no `tests/` directory |
| Mock location | **`/features/mocks/`** | ONLY valid location for mocks/fakes/stubs |
| Integration test dir | **`/robot/`** | Robot Framework only |
| Benchmark directory | **`/benchmarks/`** | ASV benchmark files |
| Task runner | **`nox`** | Never invoke tools directly |
| Type checker | **Pyright** | `nox -s typecheck` — no suppressions ever |
| Inline type suppression | **PROHIBITED** | `# type: ignore` is never acceptable |
@@ -824,6 +1442,11 @@ Release process for this project:
| TDD permanent tags | **`@tdd_issue`, `@tdd_issue_N`** | Never removed after merging |
| TDD temporary tag | **`@tdd_expected_fail`** | Removed by bug fix developer |
| Architecture spec | **`docs/specification.md`** | Authoritative — code aligns to it, not vice versa |
| Commit first line | **Verbatim from issue Metadata** | When issue prescribes one — copy exactly |
| PR dep direction | **PR → blocks → issue** | NEVER reversed — causes unresolvable deadlock |
| Multi-level testing | **Unit + Integration + Benchmarks** | Every task must address all three |
| Test failure handling | **Immediately blocking** | Resolve before any other work |
| Argument validation | **First guard in every public/protected method** | Before any other logic |
---