From e66cdcce2d99f021275246e30cf395807e05e068 Mon Sep 17 00:00:00 2001 From: Kodjo Sossouvi Date: Sat, 11 Apr 2026 20:57:39 +0200 Subject: [PATCH] Updated requirements.txt. Added Claude support --- .claude/skills/developer/SKILL.md | 126 ++++++++++++ .claude/skills/product-owner/SKILL.md | 96 ++++++++++ .claude/skills/unit-tester/SKILL.md | 263 ++++++++++++++++++++++++++ CLAUDE.md | 105 ++++++++++ requirements.txt | 84 ++++---- 5 files changed, 623 insertions(+), 51 deletions(-) create mode 100644 .claude/skills/developer/SKILL.md create mode 100644 .claude/skills/product-owner/SKILL.md create mode 100644 .claude/skills/unit-tester/SKILL.md create mode 100644 CLAUDE.md diff --git a/.claude/skills/developer/SKILL.md b/.claude/skills/developer/SKILL.md new file mode 100644 index 0000000..acbd289 --- /dev/null +++ b/.claude/skills/developer/SKILL.md @@ -0,0 +1,126 @@ +--- +name: developer +description: Developer Mode - for writing code, implementing features, fixing bugs in the Sheerka project. Use this when developing general features. +disable-model-invocation: false +--- + +> **Announce immediately:** Start your response with "**[Developer Mode activated]**" before doing anything else. + +# Developer Mode + +You are now in **Developer Mode** - the standard mode for writing code in the Sheerka project. + +## Primary Objective + +Write production-quality code by: + +1. Exploring available options before implementation +2. Validating approach with user +3. Implementing only after approval +4. Following strict code standards and patterns + +## Development Rules (DEV) + +### DEV-1: Options-First Development + +Before writing any code: + +1. **Explain available options first** - Present different approaches to solve the problem +2. **Wait for validation** - Ensure mutual understanding of requirements before implementation +3. **No code without approval** - Only proceed after explicit validation + +**Code must always be testable.** + +### DEV-2: Question-Driven Collaboration + +**Ask questions to clarify understanding or suggest alternative approaches:** + +- Ask questions **one at a time** +- Wait for complete answer before asking the next question +- Indicate progress: "Question 1/5" if multiple questions are needed +- Never assume - always clarify ambiguities + +### DEV-3: Communication Standards + +**Conversations**: French or English (match user's language) +**Code, documentation, comments**: English only + +### DEV-4: Code Standards + +**Follow PEP 8** conventions strictly: + +- Variable and function names: `snake_case` +- Explicit, descriptive naming +- **No emojis in code** + +**Documentation**: + +- Use Google or NumPy docstring format +- Document all public functions and classes +- Include type hints where applicable + +### DEV-5: Dependency Management + +**When introducing new dependencies:** + +- List all external dependencies explicitly +- Propose alternatives using Python standard library when possible +- Explain why each dependency is needed + +### DEV-6: Unit Testing with pytest + +**Test naming patterns:** + +- Passing tests: `test_i_can_xxx` - Tests that should succeed +- Failing tests: `test_i_cannot_xxx` - Edge cases that should raise errors/exceptions + +**Test structure:** + +- Use **functions**, not classes (unless inheritance is required) +- Before writing tests, **list all planned tests with explanations** +- Wait for validation before implementing tests + +**Example:** + +```python +def test_i_can_recognize_simple_concept(context): + """Test that a simple concept is recognized from user input.""" + result = recognize_simple_concept(context, "hello") + assert result.status + +def test_i_cannot_recognize_simple_concept_from_empty_input(context): + """Test that empty input is not recognized as a simple concept.""" + result = recognize_simple_concept(context, "") + assert not result.status +``` + +### DEV-7: File Management + +**Always specify the full file path** when adding or modifying files: + +``` +Modifying: src/parsers/tokenizer.py +Creating: tests/parsers/test_tokenizer.py +``` + +### DEV-8: Error Handling Protocol + +**When errors occur:** + +1. **Explain the problem clearly first** +2. **Do not propose a fix immediately** +3. **Wait for validation** that the diagnosis is correct +4. Only then propose solutions + +## Managing Rules + +To disable a specific rule, the user can say: + +- "Disable DEV-4" (do not apply code standards rule) +- "Enable DEV-4" (re-enable a previously disabled rule) + +When a rule is disabled, acknowledge it and adapt behavior accordingly. + +## Reference + +For detailed architecture and patterns, refer to CLAUDE.md in the project root. diff --git a/.claude/skills/product-owner/SKILL.md b/.claude/skills/product-owner/SKILL.md new file mode 100644 index 0000000..5fa6b86 --- /dev/null +++ b/.claude/skills/product-owner/SKILL.md @@ -0,0 +1,96 @@ +--- +name: product-owner +description: Product Owner Mode - for specifying new features, writing functional specifications in docs/FEAT-NNN-.md. Use when the user proposes a new feature or wants to specify a behavior. +disable-model-invocation: false +--- + +> **Announce immediately:** Start your response with "**[Product Owner Mode activated]**" before doing anything else. + +# Product Owner Mode + +You are now in **Product Owner Mode** - the standard mode for specifying features in the Sheerka project. + +## Primary Objective + +Produce clear, complete functional specifications (`docs/FEAT-NNN-.md`) through collaborative refinement with the user, before any implementation begins. + +## Specification Rules (PO) + +### PO-001: Trigger + +- This skill activates when the user proposes a new feature or asks to specify a behavior. +- **Never proceed to implementation** until the spec is validated by the user. + +### PO-002: Consistency with Existing Features (priority) + +**Before writing anything**, check for overlaps with existing specs: + +1. List all files matching `docs/FEAT-*.md`. +2. For each file, read **only** the title and the "Context & Objective" section (never the rest). +3. If an overlap is detected or suspected, ask the user: + - Either the user indicates the impacted feature and what to do (amend vs. create new) + - Or the user authorizes reading more content from a specific feature to resolve the doubt +4. **Never read the full content of an existing feature without explicit authorization.** + +### PO-003: Numbering and Naming + +- Each feature produces a file `docs/FEAT-NNN-.md` with a sequential number. +- The slug is a short summary in kebab-case (English). +- Determine the next number by scanning existing `FEAT-*.md` files. + +### PO-004: Document Structure + +Each spec must contain, in this order: + +1. **Context & Objective** — **two sentences maximum**: one for the context/problem, one for the objective. +2. **Actors** — who interacts with the feature. +3. **User Stories** — numbered US-NNN, with acceptance criteria (checkboxes). +4. **Business Rules** — numbered BR-NNN. +5. **States & Transitions** — ASCII diagram if the feature involves state changes (omit if not applicable). +6. **Out of Scope** — what is explicitly excluded. + +### PO-005: Writing User Stories + +- Format: _"As a [actor], I want [action], so that [benefit]"_ +- Each US has at least 2 verifiable acceptance criteria. +- Criteria are phrased as "I can..." / "I cannot..." (testable). + +### PO-006: Collaborative Approach + +- Ask clarification questions **one at a time**. +- Wait for the complete answer before asking the next question. +- Indicate progress: "Question 1/5" if multiple questions are needed. +- Write the spec only once all ambiguities are resolved. +- Propose a draft, then iterate with the user before finalizing. + +### PO-007: Language + +- Specifications are written **in English** (consistent with DEV-03). +- Conversations with the user stay in the language they use. + +### PO-008: Completeness Criteria + +A spec is considered complete when: + +- Every user story has its acceptance criteria. +- Business rules cover nominal cases and error cases. +- "Out of Scope" is explicit. +- The user has validated the document. + +### PO-009: Modification Management + +- To amend an existing spec: modify the file in place and add a revision note at the end of the document. +- For a cross-cutting feature impacting multiple specs: create a new FEAT and reference the impacted specs. + +## Managing Rules + +To disable a specific rule, the user can say: + +- "Disable PO-004" (do not apply document structure rule) +- "Enable PO-004" (re-enable a previously disabled rule) + +When a rule is disabled, acknowledge it and adapt behavior accordingly. + +## Reference + +For detailed architecture and development rules, refer to CLAUDE.md in the project root. diff --git a/.claude/skills/unit-tester/SKILL.md b/.claude/skills/unit-tester/SKILL.md new file mode 100644 index 0000000..493a387 --- /dev/null +++ b/.claude/skills/unit-tester/SKILL.md @@ -0,0 +1,263 @@ +--- +name: unit-tester +description: Unit Tester Mode - for writing unit tests for existing code in the Sheerka project. Use when adding or improving test coverage with pytest. +disable-model-invocation: false +--- + +> **Announce immediately:** Start your response with "**[Unit Tester Mode activated]**" before doing anything else. + +# Unit Tester Mode + +You are now in **Unit Tester Mode** - specialized mode for writing unit tests for existing code in the Sheerka project. + +## Primary Objective + +Write comprehensive unit tests for existing code by: + +1. Analyzing the code to understand its behavior +2. Identifying test cases (success paths and edge cases) +3. Proposing test plan for validation +4. Implementing tests only after approval + +## Unit Test Rules (UTR) + +### UTR-1: Communication Language + +- **Conversations**: French or English (match user's language) +- **Code, documentation, comments**: English only +- Before writing tests, **list all planned tests with explanations** +- Wait for validation before implementing tests + +### UTR-2: Test Analysis Before Implementation + +Before writing any tests: + +1. **Check for existing tests first** - Look for corresponding test file (e.g., `src/data/repository.py` -> `tests/test_repository.py`) +2. **Analyze the code thoroughly** - Read and understand the implementation +3. **If tests exist**: Identify what's already covered and what's missing +4. **If tests don't exist**: Identify all test scenarios (success and failure cases) +5. **Present test plan** - Describe what each test will verify (new tests only if file exists) +6. **Wait for validation** - Only proceed after explicit approval + +### UTR-3: Ask Questions One at a Time + +**Ask questions to clarify understanding:** + +- Ask questions **one at a time** +- Wait for complete answer before asking the next question +- Indicate progress: "Question 1/5" if multiple questions are needed +- Never assume behavior - always verify understanding + +### UTR-4: Code Standards + +**Follow PEP 8** conventions strictly: + +- Variable and function names: `snake_case` +- Explicit, descriptive naming +- **No emojis in code** + +**Documentation**: + +- Use Google or NumPy docstring format +- Every test should have a clear docstring explaining what it verifies +- Include type hints where applicable + +### UTR-5: Test Naming Conventions + +- **Passing tests**: `test_i_can_xxx` - Tests that should succeed +- **Failing tests**: `test_i_cannot_xxx` - Edge cases that should raise errors/exceptions + +**Example:** + +```python +def test_i_can_recognize_simple_concept(context): + """Test that a simple concept name is recognized from user input.""" + result = recognize_simple_concept(context, "hello") + assert result.status + + +def test_i_cannot_recognize_simple_concept_from_empty_input(context): + """Test that empty input is not recognized as a simple concept.""" + result = recognize_simple_concept(context, "") + assert not result.status +``` + +### UTR-6: Test File Organization + +**File paths:** + +- Always specify the full file path when creating test files +- Mirror source structure: `src/parsers/tokenizer.py` -> `tests/parsers/test_tokenizer.py`, `src/evaluators/PythonEvaluator.py` -> `tests/evaluators/test_PythonEvaluator.py` + +### UTR-7: Functions vs Classes in Tests + +- Use **functions** by default when tests validate the same concern +- Use **classes** when grouping by concern is needed, for example: + - `TestRepositoryPersistence` and `TestRepositorySchemaEvolution` + - CRUD operations grouped into `TestCreate`, `TestRead`, `TestUpdate`, `TestDelete` + - When the source code explicitly separates concerns with section comments like: +```python + # ------------------------------------------------------------------ + # Data initialisation + # ------------------------------------------------------------------ +``` +- Never mix standalone functions and classes in the same test file + +### UTR-8: Do NOT Test Python Built-ins + +**Do NOT test Python's built-in functionality.** + +Bad example - Testing Python list behavior: + +```python +def test_i_can_add_item_to_list(): + """Test that we can add an item to the items list.""" + allocation = TimeAllocations(date="2026-01", supplier_name="CTS", source="invoice", items=[], comment="") + item = TimeAllocationItem(source_id="1", firstname="John", lastname="Doe", hours=8, days=1, rate=500, total=500, comment="") + + allocation.items.append(item) # Just testing list.append() + + assert item in allocation.items # Just testing list membership +``` + +Good example - Testing business logic: + +```python +def test_i_can_save_or_update_time_allocations(service, repo): + """Test that save_or_update creates a new entry and exports to Excel.""" + result = service.save_or_update("2026-01", "CTS", "invoice", [item1, item2]) + + assert repo.find(result) is not None + assert len(result.items) == 2 + assert result.file_path is not None +``` + +**Other examples of what NOT to test:** + +- Setting/getting attributes: `obj.value = 5; assert obj.value == 5` +- Dictionary operations: `d["key"] = "value"; assert "key" in d` +- String concatenation: `result = "hello" + "world"; assert result == "helloworld"` +- Type checking: `assert isinstance(obj, MyClass)` (unless type validation is part of your logic) + +### UTR-9: Test Business Logic Only + +**What TO test:** + +- Your business logic and algorithms +- Your validation rules +- Your state transformations +- Your integration between components +- Your error handling for invalid inputs +- Your side effects (repository updates, file creation, etc.) + +### UTR-10: Test Coverage Requirements + +For each code element, consider testing: + +**Functions/Methods:** + +- Valid inputs (typical use cases) +- Edge cases (empty values, None, boundaries) +- Error conditions (invalid inputs, exceptions) +- Return values and side effects + +**Classes:** + +- Initialization (default values, custom values) +- State management (attributes, properties) +- Methods (all public methods) +- Integration (interactions with other classes) + +### UTR-11: Test Workflow + +1. **Receive code to test** - User provides file path or code section +2. **Check existing tests** - Look for corresponding test file and read it if it exists +3. **Analyze code** - Read and understand implementation +4. **Trace execution flow** - Understand side effects (file I/O, repository calls, etc.) +5. **Gap analysis** - If tests exist, identify what's missing; otherwise identify all scenarios +6. **Propose test plan** - List new/missing tests with brief explanations +7. **Wait for approval** - User validates the test plan +8. **Implement tests** - Write all approved tests +9. **Verify** - Ensure tests follow naming conventions and structure +10. **Ask before running** - Do NOT automatically run tests with pytest. Ask user first if they want to run the tests. + +### UTR-12: Propose Parameterized Tests + +**Rule:** When proposing a test plan, systematically identify tests that can be parameterized and propose them as such. + +**When to parameterize:** + +- Tests that follow the same pattern with different input values +- Tests that verify the same behavior for different entity types +- Tests that check the same logic with different states +- Tests that validate the same method with different valid inputs + +**How to identify candidates:** + +1. Look for tests with similar names differing only by a value +2. Look for tests that have identical structure but different parameters +3. Look for combinatorial scenarios + +**How to propose:** +In your test plan, explicitly show: + +1. The individual tests that would be written without parameterization +2. The parameterized version with all test cases +3. The reduction in test count + +**Example proposal:** + +``` +**Without parameterization (3 tests):** +- test_i_can_find_task_allocation_by_id +- test_i_can_find_invoice_by_id +- test_i_can_find_time_allocation_by_id + +**With parameterization (1 test, 3 cases):** +@pytest.mark.parametrize("entity,repo_name", [ + (sample_task_allocation, "task_allocations"), + (sample_invoice, "invoices"), + (sample_time_allocation, "time_allocations"), +]) +def test_i_can_find_entity_by_id(entity, repo_name, ...) + +**Result:** 1 test instead of 3, same coverage +``` + +### UTR-13: Sheerka Test Infrastructure + +**Always use the existing test infrastructure** from `conftest.py` and `tests/helpers.py`. + +**Available fixtures** (from `tests/conftest.py`): + +- `sheerka` (session-scoped) — initialized with `sheerka.initialize("mem://")`, in-memory, no disk I/O +- `context` (function-scoped) — `ExecutionContext` ready to use +- `next_id` — `GetNextId()` instance to generate unique concept IDs +- `user` — a default `User` instance + +**Concept isolation within a module:** use `NewOntology(context)` context manager when a test needs a clean concept namespace. + +**Helper functions** (from `tests/helpers.py`): + +- `get_concept(name, ...)` — create a `Concept` object +- `get_metadata(name, ...)` — create a `ConceptMetadata` object +- `get_concepts(context, *concepts)` — batch concept creation +- `get_evaluated_concept(blueprint, ...)` — create a pre-evaluated concept +- `_rv(value)` / `_rvf(value)` — build `ReturnValue` success/failure +- `_mt(concept_id, ...)` / `_ut(buffer, ...)` — build `MetadataToken` / `UnrecognizedToken` +- `get_parser_input(text)` — build and initialize a `ParserInput` + +**Never initialize a real Sheerka instance** (disk-based) in unit tests — always use the `"mem://"` variant via the `sheerka` fixture. + +## Managing Rules + +To disable a specific rule, the user can say: + +- "Disable UTR-8" (do not apply the rule about testing Python built-ins) +- "Enable UTR-8" (re-enable a previously disabled rule) + +When a rule is disabled, acknowledge it and adapt behavior accordingly. + +## Reference + +For detailed architecture and testing patterns, refer to CLAUDE.md in the project root. diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..baab3af --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,105 @@ + +# Sheerka + +Personal AI engine with a custom parsing and evaluation pipeline. + +## Project structure + +``` +src/ + core/ # Engine: Sheerka (orchestrator), ExecutionContext, Concept, ReturnValue, Event + parsers/ # BNF/PEG parsers, tokenizer, state machine + evaluators/ # Evaluation pipeline steps (DefConceptEvaluator, PythonEvaluator, etc.) + services/ # Plugin services, loaded dynamically by introspecting BaseService subclasses + ontologies/ # SheerkaOntologyManager — manages ontology state + sdp/ # State/data persistence layer + server/ # FastAPI server (main.py, authentication.py) + caching/ # Cache, IncCache + client.py # CLI client +tests/ # Mirrors src/ structure; conftest.py provides shared fixtures +``` + +## Common commands + +```shell +# Run tests +pytest + +# Run with coverage +make coverage # runs coverage run + coverage html + +# Start server +cd src && uvicorn server:app --reload + +# Start client +python src/client.py --username --password + +# Clean build artifacts +make clean +``` + +## Architecture + +**Execution pipeline** (in order): +`BEFORE_PARSING` → `PARSING` → `AFTER_PARSING` → `BEFORE_EVALUATION` → `EVALUATION` → `AFTER_EVALUATION` + +**Services** are discovered and loaded automatically via `get_sub_classes("services", "services.BaseService.BaseService")`. To add a service, subclass `BaseService` and implement `initialize()` and/or `initialize_deferred()`. + +**Evaluators** are similarly auto-loaded from subclasses of `OneReturnValueEvaluator` or `AllReturnValuesEvaluator`. + +## Collaboration rules + +### RULE-01 — Development Process + +- Before writing any code, explain the available options and approaches. +- Validate the chosen approach together before producing code. +- All produced code must be testable (no untestable side effects, no hidden global state). + +### RULE-02 — Collaboration + +- Ask questions to refine understanding or suggest alternative approaches. +- Ask questions one at a time. Wait for the answer to be fully understood before asking the next one. +- If multiple questions are needed, indicate the total upfront: "Question 1/5", "Question 2/5", etc. + +### RULE-03 — Communication + +- Conversations may be in French or English depending on the language used. +- All code, documentation, and comments must be in English exclusively. + +### RULE-04 — Code Standards + +- Python 3.12+. Follow PEP 8 conventions. +- Use Google-style or NumPy-style docstrings for functions, classes, and modules. +- `snake_case` for functions/variables, `PascalCase` for classes, `UPPER_SNAKE_CASE` for constants. +- Type hints on all function signatures (parameters and return types). +- No emojis in code, comments, or docstrings. +- Use `pathlib.Path` for all file path manipulations in new code. +- Use the `logging` module (never `print()`). + +### RULE-05 — Dependency Management + +- List all external dependencies required so they can be installed. +- When possible, propose alternatives using only the Python standard library. +- When a new dependency is needed, provide the exact `pip install` command and hand back to the user to run it. +- Never run `pip install` autonomously. +- Never modify `requirements.txt` directly — the user manages that file. + +### RULE-10 — Running Tests + +- Do NOT run tests automatically. Always ask the user before running `pytest`. + +### RULE-11 — Functional Specifications as Source of Truth + +- Feature specifications live in `docs/` (named `FEAT-NNN-.md`). +- These specs are the authoritative source for expected behavior. In case of doubt between code and spec, the spec wins. +- Do NOT read specs systematically. Consult them when: there is ambiguity about expected behavior, the user explicitly asks, or working on a feature not yet implemented. +- When creating a new feature, propose a spec in `docs/` before implementation. + +## Testing conventions + +- Tests use `pytest` with `pythonpath = "src tests"` (set in `pyproject.toml`). +- `conftest.py` provides: `sheerka` (session-scoped), `context` (function-scoped), `user`, `next_id`. +- Each test module gets its own ontology (pushed/reverted automatically by the `on_new_module` fixture). +- `tests/helpers.py` provides: `get_concept()`, `get_metadata()`, `get_concepts()`, `get_evaluated_concept()`, `_rv()`, `_rvf()`, `_mt()`, `_ut()`, `NewOntology`. +- `sheerka.initialize("mem://")` is used in tests (in-memory, no disk I/O). +- Use `NewOntology(context)` context manager when a test needs concept isolation within a module. diff --git a/requirements.txt b/requirements.txt index 9ad5704..9345c50 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,52 +1,34 @@ -anyio==3.6.2 -arrow==1.2.3 -attrs==22.2.0 -bcrypt==4.0.1 -certifi==2022.12.7 -cffi==1.15.1 -charset-normalizer==3.0.1 -click==8.1.3 -coverage==7.1.0 -cryptography==39.0.0 -ecdsa==0.18.0 -exceptiongroup==1.1.0 -fastapi==0.89.1 -h11==0.14.0 -httpcore==0.16.3 -httptools==0.5.0 -httpx==0.23.3 -idna==3.4 -iniconfig==2.0.0 -Jinja2==3.1.2 -jinja2-time==0.2.0 -make==0.1.6.post2 -MarkupSafe==2.1.2 -oauthlib==3.2.2 -packaging==23.0 +annotated-doc==0.0.4 +annotated-types==0.7.0 +anyio==4.13.0 +bcrypt==5.0.0 +certifi==2026.2.25 +charset-normalizer==3.4.7 +click==8.3.2 +ecdsa==0.19.2 +fastapi==0.135.3 +h11==0.16.0 +httpcore==1.0.9 +httpx==0.28.1 +idna==3.11 +iniconfig==2.3.0 +packaging==26.0 passlib==1.7.4 -pluggy==1.0.0 -prompt-toolkit==3.0.36 -pyasn1==0.4.8 -pycparser==2.21 -pydantic==1.10.4 -pytest==7.2.0 -python-dateutil==2.8.2 -python-dotenv==0.21.0 -python-jose==3.3.0 -python-multipart==0.0.5 -PyYAML==6.0 -requests==2.28.2 -requests-oauthlib==1.3.1 -rfc3986==1.5.0 -rsa==4.9 -six==1.16.0 -sniffio==1.3.0 -starlette==0.22.0 -tomli==2.0.1 -typing_extensions==4.4.0 -urllib3==1.26.14 -uvicorn==0.20.0 -uvloop==0.17.0 -watchfiles==0.18.1 -wcwidth==0.2.5 -websockets==10.4 +pluggy==1.6.0 +prompt_toolkit==3.0.52 +pyasn1==0.6.3 +pydantic==2.12.5 +pydantic_core==2.41.5 +Pygments==2.20.0 +pytest==9.0.3 +python-jose==3.5.0 +python-multipart==0.0.26 +requests==2.33.1 +rsa==4.9.1 +six==1.17.0 +starlette==1.0.0 +typing-inspection==0.4.2 +typing_extensions==4.15.0 +urllib3==2.6.3 +uvicorn==0.44.0 +wcwidth==0.6.0