@oleksandr.rudnychenko/sync_loop 0.3.2 → 0.3.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/README.md +0 -9
  2. package/bin/cli.ts +9 -2
  3. package/dist/bin/cli.d.ts +1 -0
  4. package/dist/bin/cli.js +6 -1
  5. package/dist/bin/cli.js.map +1 -1
  6. package/dist/src/init.js +21 -0
  7. package/dist/src/init.js.map +1 -1
  8. package/dist/src/template/.agent-loop/patterns/api-standards.md +15 -64
  9. package/dist/src/template/.agent-loop/patterns/code-patterns.md +31 -199
  10. package/dist/src/template/.agent-loop/patterns/refactoring-workflow.md +34 -61
  11. package/dist/src/template/.agent-loop/patterns/testing-guide.md +49 -162
  12. package/dist/src/template/.agent-loop/reasoning-kernel.md +68 -15
  13. package/dist/src/template/.agent-loop/validate-n.md +3 -39
  14. package/dist/src/template/AGENTS.md +33 -4
  15. package/dist/src/template/backlog-index.md +28 -0
  16. package/dist/src/template/wiring/agents-claude-architect.md +89 -0
  17. package/dist/src/template/wiring/agents-claude-fixer.md +45 -0
  18. package/dist/src/template/wiring/agents-claude.md +14 -2
  19. package/dist/src/template/wiring/agents-github-architect.md +94 -0
  20. package/dist/src/template/wiring/agents-github-fixer.md +53 -0
  21. package/dist/src/template/wiring/agents-github.md +14 -2
  22. package/dist/src/template/wiring/skills-diagnose-failure.md +34 -0
  23. package/package.json +16 -4
  24. package/src/template/.agent-loop/patterns/api-standards.md +15 -64
  25. package/src/template/.agent-loop/patterns/code-patterns.md +31 -199
  26. package/src/template/.agent-loop/patterns/refactoring-workflow.md +34 -61
  27. package/src/template/.agent-loop/patterns/testing-guide.md +49 -162
  28. package/src/template/.agent-loop/reasoning-kernel.md +68 -15
  29. package/src/template/.agent-loop/validate-n.md +3 -39
  30. package/src/template/AGENTS.md +33 -4
  31. package/src/template/backlog-index.md +28 -0
  32. package/src/template/wiring/agents-claude-architect.md +89 -0
  33. package/src/template/wiring/agents-claude-fixer.md +45 -0
  34. package/src/template/wiring/agents-claude.md +14 -2
  35. package/src/template/wiring/agents-github-architect.md +94 -0
  36. package/src/template/wiring/agents-github-fixer.md +53 -0
  37. package/src/template/wiring/agents-github.md +14 -2
  38. package/src/template/wiring/skills-diagnose-failure.md +34 -0
@@ -7,55 +7,39 @@ Referenced from [../patterns.md](../patterns.md).
7
7
 
8
8
  ## Refactoring Checklist
9
9
 
10
- ```
11
- Phase 1: PLAN
12
- Identify all files to move/rename/extract
13
- Map old imports new imports
14
- Check for documentation references (README, docstrings, agent-loop specs)
15
- ☐ Identify public interfaces that must remain stable
16
-
17
- Phase 2: EXECUTE
18
- Move files
19
- Update imports in moved files (internal references)
20
- Update all caller imports (use grep to find every reference)
21
- Update documentation examples if they contain import paths
22
- ☐ Update .agent-loop/patterns.md structure section if layout changed
23
-
24
- Phase 3: VALIDATE (NON-NEGOTIABLE)
25
- ☐ 1. Type check: run project type checker
26
- ☐ 2. Run tests: execute test suite with fail-fast
27
- ☐ 3. Check docs: grep for old import paths across all files
28
- ☐ 4. Verify no orphaned imports (unused or broken)
29
-
30
- Phase 4: DOCUMENT
31
- Update README structure section
32
- Update architecture docs if needed
33
- ☐ Create report in docs/reports/ if the refactor is major
34
- ```
10
+ **Phase 1: PLAN**
11
+ - Identify all files to move, rename, or extract
12
+ - Map old imports to new imports
13
+ - Check for documentation references (README, docstrings, agent-loop specs)
14
+ - Identify public interfaces that must remain stable
15
+
16
+ **Phase 2: EXECUTE**
17
+ - Move files to their new locations
18
+ - Update imports in moved files (internal relative references)
19
+ - Update all caller imports (search the entire codebase for every reference)
20
+ - Update documentation examples if they contain import paths
21
+ - Update `.agent-loop/patterns.md` structure section if layout changed
22
+
23
+ **Phase 3: VALIDATE (NON-NEGOTIABLE)**
24
+ 1. Type check: run the project type checker
25
+ 2. Run tests: execute the test suite with fail-fast
26
+ 3. Check docs: search for old import paths across all files
27
+ 4. Verify no orphaned imports (unused or broken)
28
+
29
+ **Phase 4: DOCUMENT**
30
+ - Update README structure section
31
+ - Update architecture docs if needed
32
+ - Create report in `docs/reports/` if the refactor is major
35
33
 
36
34
  ---
37
35
 
38
36
  ## Example: Moving a Module File
39
37
 
40
- ```bash
41
- # 1. Move file
42
- mv src/modules/old_location/processor.py src/modules/new_location/processor.py
43
-
44
- # 2. Update imports inside the moved file (internal references)
45
- # e.g., relative imports that changed due to new directory depth
46
-
47
- # 3. Find ALL references to the old path
48
- grep -r "from src.modules.old_location.processor" .
49
- grep -r "import old_location.processor" .
50
-
51
- # 4. Update each reference found:
52
- # - tests/unit/test_processor.py
53
- # - src/modules/new_location/tasks.py
54
- # - docs/architecture.md (if it mentions import paths)
55
-
56
- # 5. MANDATORY: Run validation
57
- # Type check → Tests → Grep for leftover old paths
58
- ```
38
+ 1. Move the file from its old location to the new location
39
+ 2. Update imports inside the moved file (relative references that changed due to new directory depth)
40
+ 3. Search the entire codebase for all references to the old path — tests, other modules, and documentation
41
+ 4. Update each reference found to point to the new path
42
+ 5. Run the mandatory validation: type check tests → search for leftover old paths
59
43
 
60
44
  **Why tests after docs?** Documentation often contains import examples. Tests verify imports actually work and catch typos in updated paths.
61
45
 
@@ -63,23 +47,12 @@ grep -r "import old_location.processor" .
63
47
 
64
48
  ## Example: Extracting a Function to a New Module
65
49
 
66
- ```bash
67
- # 1. Create the new module
68
- touch src/libs/parsing/helpers.py
69
-
70
- # 2. Move the function definition to the new file
71
- # Update its internal imports
72
-
73
- # 3. In the original file, replace the function body with an import:
74
- # from src.libs.parsing.helpers import parse_response
75
-
76
- # 4. Find all OTHER callers of the original location
77
- grep -r "from src.modules.analysis.utils import parse_response" .
78
-
79
- # 5. Update all callers to use the new import path
80
-
81
- # 6. VALIDATE: type check + tests + grep for old path
82
- ```
50
+ 1. Create the new module file
51
+ 2. Move the function definition to the new file and update its internal imports
52
+ 3. In the original file, replace the function body with a re-export from the new location
53
+ 4. Search for all other callers of the function at the original location
54
+ 5. Update all callers to use the new import path
55
+ 6. Run the mandatory validation: type check → tests → search for old path
83
56
 
84
57
  ---
85
58
 
@@ -7,187 +7,84 @@ Referenced from [../patterns.md](../patterns.md).
7
7
 
8
8
  ## Test Organization
9
9
 
10
- ```
11
- tests/
12
- ├── conftest.py # Shared fixtures, global setup
13
- ├── factories.py # Test data builders
14
- ├── mocks.py # Mock implementations for external deps
15
- ├── api/ # API/endpoint tests (HTTP client)
16
- ├── integration/ # Multi-component workflow tests
17
- └── unit/ # Pure logic tests (no I/O)
18
- ```
10
+ Organize tests into a top-level `tests/` directory with clear separation:
11
+
12
+ | Directory | Purpose |
13
+ |-----------|---------|
14
+ | `tests/conftest` or `tests/helpers` | Shared fixtures, global setup |
15
+ | `tests/factories` | Test data builders |
16
+ | `tests/mocks` | Mock implementations for external dependencies |
17
+ | `tests/api/` | API/endpoint tests (HTTP client) |
18
+ | `tests/integration/` | Multi-component workflow tests |
19
+ | `tests/unit/` | Pure logic tests (no I/O) |
19
20
 
20
21
  ---
21
22
 
22
23
  ## Pattern 1: Fixture-Based Setup
23
24
 
24
- ```python
25
- # Environment isolation — reset global state each test
26
- @pytest.fixture(autouse=True)
27
- def reset_context():
28
- """Reset global state before each test."""
29
- import app.context
30
- app.context._context = None
31
- yield
32
- app.context._context = None
33
-
34
- # Test app configuration
35
- @pytest.fixture
36
- def test_app(monkeypatch: pytest.MonkeyPatch, tmp_path: Path):
37
- """Configure app with test-safe environment."""
38
- monkeypatch.setenv("APP_ENV", "testing")
39
- monkeypatch.setenv("ENABLE_BACKGROUND_TASKS", "0")
40
- yield create_app()
41
-
42
- # API client for endpoint tests
43
- @pytest.fixture
44
- def client(test_app):
45
- return TestClient(test_app)
46
- ```
25
+ Define reusable **fixtures** (setup/teardown helpers) that isolate test state:
26
+
27
+ - **Environment isolation fixture**: resets any module-level singletons or global state before and after each test. Ensures one test cannot leak state into another.
28
+ - **Test app fixture**: configures the application with test-safe environment variables (e.g., test database URL, disabled background tasks) and yields a configured app instance.
29
+ - **Client fixture**: wraps the test app in an HTTP test client for endpoint-level tests.
30
+
31
+ Each fixture is scoped to the narrowest lifecycle needed — per-test for state resets, per-session for expensive resources like database connections.
47
32
 
48
33
  ---
49
34
 
50
35
  ## Pattern 2: Factory Pattern for Test Data
51
36
 
52
- ```python
53
- class EntityFactory:
54
- @staticmethod
55
- def create(
56
- id: str | None = None,
57
- name: str = "Test Entity",
58
- entity_type: str = "default",
59
- **extras: Any,
60
- ) -> dict[str, Any]:
61
- return {
62
- "id": id or str(uuid4()),
63
- "name": name,
64
- "metadata": {"type": entity_type, **extras},
65
- }
66
-
67
- @staticmethod
68
- def with_full_analysis() -> dict[str, Any]:
69
- """Semantic constructor for entity with all analysis fields populated."""
70
- return EntityFactory.create(
71
- name="Fully Analyzed Entity",
72
- entity_type="analyzed",
73
- score=85.0,
74
- grade="B",
75
- )
76
- ```
37
+ Create a **factory class** (or set of builder functions) that produces valid test entities with sensible defaults. Each factory method accepts optional overrides via keyword arguments so tests only specify the fields relevant to the scenario.
38
+
39
+ Provide **semantic constructors** — named factory methods like `with_full_analysis()` or `as_admin_user()` — that configure the entity for a specific test scenario. This makes test setup self-documenting and avoids duplicated setup logic across test files.
77
40
 
78
41
  ---
79
42
 
80
43
  ## Pattern 3: Mock External Dependencies
81
44
 
82
- ```python
83
- class MockExternalService:
84
- """Mock for any external service boundary (LLM, API, storage)."""
85
- def __init__(self, response: dict | str | None = None):
86
- self.response = response or self._default_response()
87
- self.calls: list[dict] = []
88
-
89
- async def __call__(self, prompt: str, context: str, **kwargs):
90
- self.calls.append({"prompt": prompt, "context": context})
91
- return json.dumps(self.response), {}
92
-
93
- @property
94
- def call_count(self) -> int:
95
- return len(self.calls)
96
- ```
97
-
98
- Usage:
99
- ```python
100
- @pytest.fixture
101
- def mock_service() -> MockExternalService:
102
- return MockExternalService(response={"score": 85})
103
-
104
- def test_analysis_delegates_to_service(mock_service):
105
- service = AnalysisService(external=mock_service)
106
- result = service.analyze(...)
107
- assert mock_service.call_count == 1
108
- ```
45
+ Define a **mock class** for each external boundary (LLM, HTTP API, storage backend, message queue). The mock:
109
46
 
110
- ---
47
+ - Accepts a configurable response via its constructor
48
+ - Records every call (arguments, timestamps) in an internal list
49
+ - Returns the configured response on each invocation
50
+ - Exposes a `call_count` property for verification
111
51
 
112
- ## Pattern 4: Class-Based Test Organization
52
+ Tests inject the mock via fixture, replacing the real dependency. After the test action, assertions verify both the result and the mock's call history.
113
53
 
114
- ```python
115
- class TestParseResponse:
116
- def test_valid_json_response(self):
117
- response = '{"entity_type": "analyzed", "score": 85}'
118
- result = parse_response(response)
119
- assert result.entity_type == EntityType.ANALYZED
54
+ ---
120
55
 
121
- def test_invalid_json_fallback(self):
122
- result = parse_response("Not JSON")
123
- assert result.entity_type == EntityType.UNKNOWN
56
+ ## Pattern 4: Class-Based Test Organization
124
57
 
125
- def test_missing_fields_use_defaults(self):
126
- result = parse_response('{"entity_type": "analyzed"}')
127
- assert result.score == 0.0
128
- ```
58
+ Group related test cases into a **test class** named after the unit under test (e.g., `TestParseResponse`, `TestOrderService`). Each method within the class tests one behavior: happy path, error path, edge case, or default behavior. The class name provides namespace grouping in test runner output.
129
59
 
130
60
  ---
131
61
 
132
62
  ## Pattern 5: Parametrized Tests
133
63
 
134
- ```python
135
- @pytest.mark.parametrize("score,expected_grade", [
136
- (95, "A"), (90, "A"),
137
- (89.9, "B"), (85, "B"), (80, "B"),
138
- (79, "C"), (70, "C"),
139
- (69, "D"), (60, "D"),
140
- (59, "F"), (0, "F"),
141
- ])
142
- def test_grade_thresholds(score: float, expected_grade: str):
143
- assert compute_grade(score) == expected_grade
144
- ```
64
+ Use the test framework's **parametrize** mechanism to run one test function across multiple input/output pairs. Define the parameter sets as a list of tuples — each tuple contains the input values and the expected outcome. This eliminates repetitive test methods for boundary-value or threshold logic.
145
65
 
146
66
  ---
147
67
 
148
68
  ## Pattern 6: Three-Layer Test Strategy
149
69
 
150
- ```python
151
- # UNIT: Pure logic, no I/O
152
- def test_parse_response():
153
- result = parse_response('{"entity_type": "analyzed"}')
154
- assert result.entity_type == EntityType.ANALYZED
155
-
156
- # INTEGRATION: Multiple components, mocked external I/O
157
- def test_analysis_pipeline(mock_service, mock_repository):
158
- service = AnalysisService(external=mock_service, repo=mock_repository)
159
- report = service.analyze(entities=[...])
160
- assert report.aggregate_score > 0
161
-
162
- # API: HTTP endpoint, full stack with test client
163
- def test_analyze_endpoint(client, mock_data):
164
- response = client.post("/api/v1/analyze", json=mock_data)
165
- assert response.status_code == 200
166
- assert "score" in response.json()
167
- ```
70
+ Structure tests into three layers with distinct characteristics:
71
+
72
+ - **Unit tests**: Pure logic, no I/O, no external dependencies. Test a single function or class method in isolation. Fast (< 10ms each).
73
+ - **Integration tests**: Multiple components wired together, external I/O mocked at the boundary. Test that services, repositories, and adapters compose correctly.
74
+ - **API tests**: Full HTTP request/response cycle through a test client. Verify status codes, response shapes, and error envelopes.
168
75
 
169
76
  ---
170
77
 
171
78
  ## Pattern 7: Assertion Patterns
172
79
 
173
- ```python
174
- # ✅ Specific property checks
175
- assert report.task_id == "task-1"
176
- assert len(report.metrics) > 0
177
- assert "total_items" in [m.name for m in report.metrics]
80
+ Write assertions that verify **specific properties**, not just truthiness:
178
81
 
179
- # Range/constraint checks
180
- assert 0 <= result.score <= 100
181
- assert result.entity_type in EntityType
82
+ - Check exact field values on result objects
83
+ - Verify collection lengths and membership
84
+ - Use range/constraint assertions (value within expected bounds, enum membership)
85
+ - Assert on collection-wide properties (all items satisfy a predicate, at least one item matches)
182
86
 
183
- # Collection checks
184
- assert all(m.value >= 0 for m in report.metrics)
185
- assert any(r.entity_type == "analyzed" for r in results)
186
-
187
- # ❌ Vague — what is being verified?
188
- assert report
189
- assert result is not None
190
- ```
87
+ Avoid vague assertions like "result is not None" or bare truthiness checks — they pass on wrong data.
191
88
 
192
89
  ---
193
90
 
@@ -195,14 +92,13 @@ assert result is not None
195
92
 
196
93
  Format: `test_<action>_<condition>_<outcome>`
197
94
 
198
- ```
199
- test_returns_report # Basic happy path
200
- test_metrics_computed_correctly # Specific behavior
201
- test_unknown_type_falls_back_to_default # Edge case
202
- test_invalid_json_fallback # Error handling
203
- test_missing_fields_use_defaults # Default behavior
204
- test_empty_input_returns_empty_report # Boundary condition
205
- ```
95
+ Examples:
96
+ - `test_returns_report` basic happy path
97
+ - `test_metrics_computed_correctly` specific behavior
98
+ - `test_unknown_type_falls_back_to_default` edge case
99
+ - `test_invalid_json_fallback` error handling
100
+ - `test_missing_fields_use_defaults` default behavior
101
+ - `test_empty_input_returns_empty_report` boundary condition
206
102
 
207
103
  ---
208
104
 
@@ -237,16 +133,7 @@ test_empty_input_returns_empty_report # Boundary condition
237
133
  2. **Adjacent modules second** — run tests for callers/consumers
238
134
  3. **Full suite last** — once local confidence is high, run everything
239
135
 
240
- ```bash
241
- # Targeted
242
- pytest tests/unit/test_processor.py -x -v
243
-
244
- # Adjacent
245
- pytest tests/unit/ tests/integration/ -x -v -k "processor or analysis"
246
-
247
- # Full suite
248
- pytest tests/ -x -v
249
- ```
136
+ Use the project's test runner with verbose and fail-fast flags. Filter by keyword or path to target specific modules during iterative development.
250
137
 
251
138
  ---
252
139
 
@@ -312,20 +312,39 @@ LEARN:
312
312
 
313
313
  ### 7. REPORT (Session Log)
314
314
 
315
- After completing a non-trivial task, persist a session summary to `docs/reports/`.
315
+ The REPORT stage produces exactly one of three outcomes: a **report**, a **backlog task**, or **nothing**.
316
+ Apply the decision tree below — follow it top to bottom, take the first matching branch.
316
317
 
317
- **When to write a report:**
318
+ #### Decision Tree: Report vs Backlog vs Skip
318
319
 
319
- | Condition | Report Required | Format |
320
- |-----------|----------------|--------|
321
- | Multi-file refactoring | Yes | Full report |
322
- | New feature / module added | Yes | Full report |
323
- | Bug fix with root cause analysis | Yes | Abbreviated (scope + fix + verification) |
324
- | Architecture or pattern change | Yes | Full report + patterns.md update |
325
- | Single-file cosmetic fix | No | — |
326
- | Documentation-only update | No | — |
320
+ ```
321
+ Was work implemented and committed this session?
322
+
323
+ ├─ YES Did the work touch multiple files or change architecture/patterns?
324
+ │ │
325
+ │ ├─ YES Write REPORT to docs/reports/
326
+ │ │ (multi-file refactor, new feature, root-cause fix,
327
+ │ │ architecture change, pattern change)
328
+ │ │
329
+ │ └─ NO → SKIP (single-file edit, cosmetic fix, docs-only update)
330
+
331
+ └─ NO → Was an investigation or plan produced without implementation?
332
+
333
+ ├─ YES → Write BACKLOG TASK to docs/backlog/
334
+ │ (needs approval, complex decomposition required,
335
+ │ lower priority than current sprint, blocked on dependency)
336
+
337
+ └─ NO → SKIP (question answered, context gathered, trivial lookup)
338
+ ```
339
+
340
+ **Key distinction:** Reports document **completed work**. Backlog tasks document **planned but unexecuted work**.
341
+ Never create both for the same task. If you implemented the work, write a report. If you only planned it, write a backlog task.
342
+
343
+ #### Report: Completed Work
344
+
345
+ **Trigger:** Implementation was done this session AND touched ≥2 files or changed architecture/patterns.
327
346
 
328
- **Report structure:**
347
+ **Structure:**
329
348
 
330
349
  ```markdown
331
350
  # {Short Description}
@@ -355,10 +374,44 @@ After completing a non-trivial task, persist a session summary to `docs/reports/
355
374
  {What was persisted to patterns.md / patterns/ specs / glossary}
356
375
  ```
357
376
 
358
- **File placement:**
359
- - Report: `docs/reports/YYYY-MM-DD-{short-description}.md`
360
- - Supporting artifacts: `docs/reports/artifacts/`
377
+ **File:** `docs/reports/YYYY-MM-DD-{slug}.md`
378
+ **Artifacts:** `docs/reports/artifacts/`
379
+
380
+ #### Backlog Task: Planned but Deferred Work
381
+
382
+ **Trigger:** Investigation or planning was done this session BUT implementation was NOT executed.
383
+ Reasons to defer: needs approval, requires decomposition, lower priority, blocked on external dependency.
384
+
385
+ **Structure:**
386
+
387
+ ```markdown
388
+ # {Task Title}
389
+
390
+ **Date:** YYYY-MM-DD
391
+ **Priority:** P0–P3
392
+ **State:** planned
393
+
394
+ ## Context
395
+ {Why this task exists — what was investigated, what triggered it}
396
+
397
+ ## Action Plan
398
+ {Step-by-step implementation plan with file paths and scope}
399
+
400
+ ## Acceptance Criteria
401
+ {Concrete conditions that define "done" — gate results, test coverage, behavior}
402
+
403
+ ## Dependencies
404
+ {What must be resolved before this can start — other tasks, approvals, external}
405
+ ```
406
+
407
+ **File:** `docs/backlog/YYYY-MM-DD-{slug}.md`
408
+ **Index:** After creating the task file, add a row to `docs/backlog/index.md` with task number, title, priority (P0–P3), state (`planned`), date, and filename.
409
+
410
+ #### Common Rules
411
+
361
412
  - Naming: date-prefixed, lowercase-kebab-case, no `_v1`/`_new` suffixes
413
+ - Never create both a report and a backlog task for the same piece of work
414
+ - If a backlog task is later implemented, mark it `done` in the index and write a report for the implementation session
362
415
 
363
416
  ---
364
417
 
@@ -460,7 +513,7 @@ LEARN
460
513
  [one-line do-more/do-less heuristic]
461
514
 
462
515
  REPORT (if non-trivial)
463
- [docs/reports/YYYY-MM-DD-{slug}.md created — or "skipped (trivial)"]
516
+ [docs/reports/YYYY-MM-DD-{slug}.md | docs/backlog/YYYY-MM-DD-{slug}.md — or "skipped (trivial)"]
464
517
  ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
465
518
  ```
466
519
 
@@ -53,51 +53,15 @@ When modifying any of these, check all neighbors in the coupling path.
53
53
 
54
54
  ### Shapes
55
55
 
56
- The **signature contract** of a function, method, or class:
57
-
58
- ```python
59
- # Shape = name + parameters + return type + raises
60
- def query(
61
- self,
62
- collection: str,
63
- query_text: str,
64
- *,
65
- filters: dict | None = None,
66
- limit: int = 10,
67
- ) -> list[Result]:
68
- ...
69
- ```
70
-
71
- A shape change is anything that alters the call contract:
72
- adding/removing parameters, changing types, or modifying return types.
56
+ The **signature contract** of a function, method, or class: its name, parameter names and types (including keyword-only and optional parameters), return type, and declared exceptions. A shape change is anything that alters the call contract: adding or removing parameters, changing parameter or return types, or modifying exception declarations.
73
57
 
74
58
  ### Boundaries
75
59
 
76
- The **module interface** — what is exported/public:
77
-
78
- ```python
79
- # module/__init__.py
80
- from .service import MyService # Public boundary
81
- from .routes import router # Public boundary
82
-
83
- # Private (not exported) — can change freely
84
- # from .internal import _helper
85
- ```
86
-
87
- Boundary changes affect every consumer that imports from the module.
60
+ The **module interface** — the set of symbols explicitly exported as public. Public exports are the symbols listed in the module's index file or namespace declaration. Everything not exported is private and can change freely. Boundary changes affect every consumer that imports from the module.
88
61
 
89
62
  ### Bridges
90
63
 
91
- The **contracts between modules** — how they communicate:
92
-
93
- ```python
94
- # Bridge: module_a → module_b
95
- # Contract: ServiceA.process() returns list[Result]
96
- # Consumer: ServiceB expects this shape
97
-
98
- # If ServiceA.process() changes return type:
99
- # → ServiceB breaks (bridge violation)
100
- ```
64
+ The **contracts between modules** — how one module's output becomes another module's input. A bridge connects a producer (the function or service returning data) to a consumer (the function or service expecting that data). If the producer changes the shape of its output, the consumer breaks unless it is also updated.
101
65
 
102
66
  ---
103
67
 
@@ -147,11 +147,40 @@ If uncertain, choose isolated and reversible changes.
147
147
 
148
148
  ---
149
149
 
150
- ## 9. Reporting & Artifacts
150
+ ## 9. Reporting, Backlog & Artifacts
151
151
 
152
- - Reports: `docs/reports/YYYY-MM-DD-{slug}.md`
152
+ The REPORT stage (stage 7) produces exactly one of three outcomes per task:
153
+
154
+ ```
155
+ Work implemented this session?
156
+ ├─ YES + multi-file or architecture change → REPORT
157
+ ├─ YES + single-file cosmetic/docs-only → SKIP
158
+ ├─ NO + investigation/plan produced → BACKLOG TASK
159
+ └─ NO + trivial lookup/question → SKIP
160
+ ```
161
+
162
+ **Key rule:** Reports record **completed work**. Backlog tasks record **planned but unexecuted work**. Never create both for the same task.
163
+
164
+ ### Reports (completed work)
165
+
166
+ - Path: `docs/reports/YYYY-MM-DD-{slug}.md`
153
167
  - Artifacts: `docs/reports/artifacts/`
154
- - Learning memory: `.agent-loop/patterns.md` and `.agent-loop/patterns/*.md`
168
+ - Trigger: implementation was done this session AND touched ≥2 files or changed architecture/patterns
169
+ - Contents: summary, scope, changes, verification results, learned patterns
170
+
171
+ ### Backlog (planned but deferred work)
172
+
173
+ - Index: `docs/backlog/index.md` — priority-sorted table with task state
174
+ - Tasks: `docs/backlog/YYYY-MM-DD-{slug}.md` — one file per task
175
+ - Trigger: investigation or planning was done BUT implementation was NOT executed (needs approval, requires decomposition, lower priority, blocked on dependency)
176
+ - Contents: context, Action Plan, acceptance criteria, priority (P0–P3), dependencies
177
+ - After creating a task file, add a row to `docs/backlog/index.md`
178
+ - When a backlog task is later implemented, mark it `done` in the index and write a report for that session
179
+
180
+ ### Learning Memory
181
+
182
+ - `.agent-loop/patterns.md` and `.agent-loop/patterns/*.md`
183
+ - Updated during LEARN (stage 6), independent of report/backlog routing
155
184
 
156
- Create reports for non-trivial work (multi-file refactor, root-cause fix, architecture change).
185
+ Full decision tree and templates: see [reasoning-kernel.md § REPORT](.agent-loop/reasoning-kernel.md).
157
186
 
@@ -0,0 +1,28 @@
1
+ # Backlog
2
+
3
+ Planned tasks awaiting implementation. Each task is a separate file in this folder.
4
+
5
+ ## Priority Levels
6
+
7
+ | Priority | Meaning |
8
+ |----------|---------|
9
+ | **P0 — Critical** | Blocking issue or regression. Must be resolved before any other work. |
10
+ | **P1 — High** | Important feature or fix. Next in queue after critical items. |
11
+ | **P2 — Normal** | Standard work item. Implement when bandwidth allows. |
12
+ | **P3 — Low** | Nice-to-have improvement. Defer until higher-priority items clear. |
13
+
14
+ ## Task States
15
+
16
+ | State | Meaning |
17
+ |-------|---------|
18
+ | `planned` | Investigated and planned. Action Plan written. Ready to implement. |
19
+ | `in-progress` | Currently being worked on. |
20
+ | `blocked` | Cannot proceed — dependency or question unresolved. |
21
+ | `done` | Implemented and validated. Keep for reference, then archive. |
22
+
23
+ ## Index
24
+
25
+ <!-- Add rows as tasks are created. Keep sorted by priority then date. -->
26
+
27
+ | # | Task | Priority | State | Created | File |
28
+ |---|------|----------|-------|---------|------|