guardian-framework 0.1.0
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.
- package/LICENSE +21 -0
- package/README.md +463 -0
- package/dist/cli.js +12958 -0
- package/dist/exports.js +12765 -0
- package/package.json +61 -0
- package/templates/languages/go-patterns.md +411 -0
- package/templates/languages/java-patterns.md +545 -0
- package/templates/languages/python-patterns.md +312 -0
- package/templates/languages/rust-patterns.md +232 -0
- package/templates/languages/typescript-patterns.md +313 -0
- package/templates/pi/INDEX.md +437 -0
- package/templates/pi/agent/AGENTS.md +166 -0
- package/templates/pi/agents/architecture-coordinator.md +40 -0
- package/templates/pi/agents/architecture-validator.md +36 -0
- package/templates/pi/agents/bootstrap-implementer.md +37 -0
- package/templates/pi/agents/issue-factory.md +31 -0
- package/templates/pi/agents/operations-validator.md +32 -0
- package/templates/pi/agents/security-validator.md +33 -0
- package/templates/pi/architecture/CHANGELOG.md +78 -0
- package/templates/pi/architecture/decisions/ADR-template.md +76 -0
- package/templates/pi/architecture/diagrams/system-overview.md +159 -0
- package/templates/pi/architecture/modules/module-template.md +152 -0
- package/templates/pi/context/checklists.md +91 -0
- package/templates/pi/context/domain-workflow.md +180 -0
- package/templates/pi/context/output-formats.md +135 -0
- package/templates/pi/context/patterns-base.md +47 -0
- package/templates/pi/context/patterns.md +38 -0
- package/templates/pi/context/project.md +88 -0
- package/templates/pi/domain/exploration.md +93 -0
- package/templates/pi/domain/ubiquitous-language.md +24 -0
- package/templates/pi/extensions/architect-lib/generators.ts +528 -0
- package/templates/pi/extensions/architect-lib/helpers.ts +344 -0
- package/templates/pi/extensions/architect-lib/types.ts +117 -0
- package/templates/pi/extensions/architect.ts +1425 -0
- package/templates/pi/extensions/ask-user-question.ts +579 -0
- package/templates/pi/extensions/bash-guard.ts +556 -0
- package/templates/pi/extensions/config-reload.ts +115 -0
- package/templates/pi/extensions/coordinator.ts +304 -0
- package/templates/pi/extensions/curator.ts +543 -0
- package/templates/pi/extensions/domain-explorer.ts +990 -0
- package/templates/pi/extensions/filechanges.ts +656 -0
- package/templates/pi/extensions/goal-loop.ts +717 -0
- package/templates/pi/extensions/hooks.ts +452 -0
- package/templates/pi/extensions/kanban.ts +547 -0
- package/templates/pi/extensions/pipeline.ts +1246 -0
- package/templates/pi/extensions/plan-mode.ts +209 -0
- package/templates/pi/extensions/project-scaffolder.ts +284 -0
- package/templates/pi/extensions/read-only-mode.ts +192 -0
- package/templates/pi/extensions/redaction.ts +128 -0
- package/templates/pi/extensions/session-persistence.ts +174 -0
- package/templates/pi/extensions/slash-commands.ts +229 -0
- package/templates/pi/extensions/snippets.ts +201 -0
- package/templates/pi/extensions/validation-runner.ts +100 -0
- package/templates/pi/github/agents/architecture-coordinator.agent.md +27 -0
- package/templates/pi/github/agents/architecture-validator.agent.md +20 -0
- package/templates/pi/github/agents/bootstrap-implementer.agent.md +20 -0
- package/templates/pi/github/agents/epic-planner.agent.md +70 -0
- package/templates/pi/github/agents/issue-factory.agent.md +20 -0
- package/templates/pi/github/agents/operations-validator.agent.md +20 -0
- package/templates/pi/github/agents/security-validator.agent.md +20 -0
- package/templates/pi/github/copilot/settings.json +16 -0
- package/templates/pi/github/copilot-instructions.md +155 -0
- package/templates/pi/github/instructions/architecture.instructions.md +71 -0
- package/templates/pi/github/instructions/validation.instructions.md +69 -0
- package/templates/pi/github/workflows/01-planning-workflow.md +75 -0
- package/templates/pi/github/workflows/02-issue-generation-workflow.md +69 -0
- package/templates/pi/github/workflows/03-implementation-workflow.md +80 -0
- package/templates/pi/github/workflows/04-validation-workflow.md +68 -0
- package/templates/pi/preflight_report.json +99 -0
- package/templates/pi/prompts/blueprint-update.md +262 -0
- package/templates/pi/prompts/blueprint-validate.md +218 -0
- package/templates/pi/prompts/bug-fix.md +50 -0
- package/templates/pi/prompts/ci-blueprint.md +131 -0
- package/templates/pi/prompts/context-refresh.md +258 -0
- package/templates/pi/prompts/epic-plan.md +356 -0
- package/templates/pi/prompts/epic-template.md +186 -0
- package/templates/pi/prompts/feature-development.md +131 -0
- package/templates/pi/prompts/git-issues.md +243 -0
- package/templates/pi/prompts/hotfix.md +71 -0
- package/templates/pi/prompts/issue-closeout.md +342 -0
- package/templates/pi/prompts/issue-draft.md +218 -0
- package/templates/pi/prompts/issue-implementation-series.md +173 -0
- package/templates/pi/prompts/issue-merge.md +372 -0
- package/templates/pi/prompts/issue-template-set.md +392 -0
- package/templates/pi/prompts/issue-template.md +207 -0
- package/templates/pi/prompts/pattern-extract.md +269 -0
- package/templates/pi/prompts/plan-to-issues.md +430 -0
- package/templates/pi/prompts/refactoring.md +82 -0
- package/templates/pi/prompts/scope-analyzer.md +254 -0
- package/templates/pi/prompts/sync-check.md +230 -0
- package/templates/pi/scripts/categorize-issues.sh +171 -0
- package/templates/pi/scripts/ci/check_architecture_conformance.sh +748 -0
- package/templates/pi/scripts/ci/check_planning_packet.py +228 -0
- package/templates/pi/scripts/ci/run_hardening_stages.sh +264 -0
- package/templates/pi/scripts/ci/run_preflight.sh +649 -0
- package/templates/pi/scripts/ci/run_stage.sh +193 -0
- package/templates/pi/scripts/ci/stage_docs_policy.sh +82 -0
- package/templates/pi/scripts/ci/stage_integration.sh +3 -0
- package/templates/pi/scripts/ci/stage_lint.sh +130 -0
- package/templates/pi/scripts/ci/stage_migration_verify.sh +3 -0
- package/templates/pi/scripts/ci/stage_package_build.sh +3 -0
- package/templates/pi/scripts/ci/stage_release_readiness.sh +3 -0
- package/templates/pi/scripts/ci/stage_remaining.sh +242 -0
- package/templates/pi/scripts/ci/stage_security.sh +3 -0
- package/templates/pi/scripts/ci/stage_static_analysis.sh +114 -0
- package/templates/pi/scripts/ci/stage_unit.sh +119 -0
- package/templates/pi/scripts/ci/validate_agent_output.py +181 -0
- package/templates/pi/scripts/ci/validate_agent_output.sh +243 -0
- package/templates/pi/scripts/create-feature-branch.sh +136 -0
- package/templates/pi/scripts/create-mr.sh +117 -0
- package/templates/pi/scripts/fetch-issues.sh +131 -0
- package/templates/pi/scripts/generate-architecture.sh +161 -0
- package/templates/pi/scripts/git/close-epic.sh +69 -0
- package/templates/pi/scripts/git/close-issue.sh +35 -0
- package/templates/pi/scripts/git/create-tracking-issue.sh +174 -0
- package/templates/pi/scripts/git/link-issue-to-epic.sh +51 -0
- package/templates/pi/scripts/git/update-tracking-issue.sh +66 -0
- package/templates/pi/scripts/languages/go/validate-architecture.sh +139 -0
- package/templates/pi/scripts/languages/go/validate-canonical.sh +129 -0
- package/templates/pi/scripts/languages/go/validate-ci.sh +132 -0
- package/templates/pi/scripts/languages/go/validate-integration.sh +156 -0
- package/templates/pi/scripts/languages/go/validate-operations.sh +146 -0
- package/templates/pi/scripts/languages/go/validate-security.sh +135 -0
- package/templates/pi/scripts/languages/go/validate-tests.sh +125 -0
- package/templates/pi/scripts/languages/java/validate-annotations.sh +185 -0
- package/templates/pi/scripts/languages/java/validate-architecture.sh +159 -0
- package/templates/pi/scripts/languages/java/validate-canonical.sh +114 -0
- package/templates/pi/scripts/languages/java/validate-ci.sh +269 -0
- package/templates/pi/scripts/languages/java/validate-integration.sh +149 -0
- package/templates/pi/scripts/languages/java/validate-operations.sh +142 -0
- package/templates/pi/scripts/languages/java/validate-security.sh +174 -0
- package/templates/pi/scripts/languages/java/validate-spring-architecture.sh +227 -0
- package/templates/pi/scripts/languages/java/validate-tests.sh +159 -0
- package/templates/pi/scripts/languages/python/validate-architecture.sh +99 -0
- package/templates/pi/scripts/languages/python/validate-canonical.sh +124 -0
- package/templates/pi/scripts/languages/python/validate-ci.sh +130 -0
- package/templates/pi/scripts/languages/python/validate-integration.sh +119 -0
- package/templates/pi/scripts/languages/python/validate-operations.sh +107 -0
- package/templates/pi/scripts/languages/python/validate-security.sh +68 -0
- package/templates/pi/scripts/languages/python/validate-tests.sh +102 -0
- package/templates/pi/scripts/languages/rust/validate-architecture.sh +188 -0
- package/templates/pi/scripts/languages/rust/validate-canonical.sh +146 -0
- package/templates/pi/scripts/languages/rust/validate-ci.sh +147 -0
- package/templates/pi/scripts/languages/rust/validate-integration.sh +149 -0
- package/templates/pi/scripts/languages/rust/validate-operations.sh +154 -0
- package/templates/pi/scripts/languages/rust/validate-security.sh +153 -0
- package/templates/pi/scripts/languages/rust/validate-tests.sh +150 -0
- package/templates/pi/scripts/languages/typescript/validate-architecture.sh +157 -0
- package/templates/pi/scripts/languages/typescript/validate-canonical.sh +135 -0
- package/templates/pi/scripts/languages/typescript/validate-ci.sh +244 -0
- package/templates/pi/scripts/languages/typescript/validate-integration.sh +166 -0
- package/templates/pi/scripts/languages/typescript/validate-operations.sh +162 -0
- package/templates/pi/scripts/languages/typescript/validate-security.sh +169 -0
- package/templates/pi/scripts/languages/typescript/validate-tests.sh +158 -0
- package/templates/pi/scripts/merge-mr.sh +95 -0
- package/templates/pi/scripts/mr-validation.sh +228 -0
- package/templates/pi/scripts/validate-architecture-readiness.sh +153 -0
- package/templates/pi/scripts/validate-architecture.sh +22 -0
- package/templates/pi/scripts/validate-canonical.sh +22 -0
- package/templates/pi/scripts/validate-ci.sh +37 -0
- package/templates/pi/scripts/validate-integration.sh +22 -0
- package/templates/pi/scripts/validate-operations.sh +22 -0
- package/templates/pi/scripts/validate-security.sh +22 -0
- package/templates/pi/scripts/validate-tests.sh +22 -0
- package/templates/pi/scripts/validate-ubiquitous-language.sh +291 -0
- package/templates/pi/scripts/validation-cache.sh +139 -0
- package/templates/pi/skills/agents/architecture-coordinator.md +178 -0
- package/templates/pi/skills/agents/architecture-generator.md +79 -0
- package/templates/pi/skills/agents/architecture-validator.md +74 -0
- package/templates/pi/skills/agents/ci-mr-validator.md +46 -0
- package/templates/pi/skills/agents/code-developer.md +76 -0
- package/templates/pi/skills/agents/commit.md +46 -0
- package/templates/pi/skills/agents/curator.md +71 -0
- package/templates/pi/skills/agents/debug.md +59 -0
- package/templates/pi/skills/agents/documentation-maintainer.md +36 -0
- package/templates/pi/skills/agents/goal-loop.md +125 -0
- package/templates/pi/skills/agents/hooks.md +122 -0
- package/templates/pi/skills/agents/integration-validator.md +35 -0
- package/templates/pi/skills/agents/issue-creator.md +75 -0
- package/templates/pi/skills/agents/issue-factory.md +143 -0
- package/templates/pi/skills/agents/kanban.md +85 -0
- package/templates/pi/skills/agents/land.md +59 -0
- package/templates/pi/skills/agents/operations-validator.md +43 -0
- package/templates/pi/skills/agents/pipeline.md +113 -0
- package/templates/pi/skills/agents/plan-mode.md +77 -0
- package/templates/pi/skills/agents/pull.md +40 -0
- package/templates/pi/skills/agents/push.md +41 -0
- package/templates/pi/skills/agents/security-validator.md +85 -0
- package/templates/pi/skills/agents/session-persistence.md +119 -0
- package/templates/pi/skills/agents/slash-commands.md +117 -0
- package/templates/pi/skills/agents/snippets.md +99 -0
- package/templates/pi/skills/agents/subagent-registry.md +78 -0
- package/templates/pi/skills/agents/test-validator.md +42 -0
- package/templates/pi/skills/validators/architecture-validator.md +43 -0
- package/templates/pi/skills/validators/ci-validator.md +27 -0
- package/templates/pi/skills/validators/context-compaction.md +73 -0
- package/templates/pi/skills/validators/integration-validator.md +38 -0
- package/templates/pi/skills/validators/model-registry.md +96 -0
- package/templates/pi/skills/validators/operations-validator.md +34 -0
- package/templates/pi/skills/validators/security-guards.md +72 -0
- package/templates/pi/skills/validators/security-validator.md +41 -0
- package/templates/pi/skills/validators/system-prompt-tiers.md +69 -0
- package/templates/pi/skills/validators/test-validator.md +33 -0
- package/templates/pi/types.ts +62 -0
- package/templates/pi/validators/README.md +93 -0
- package/templates/pi/validators/default.toml +209 -0
- package/templates/pi/validators/spring.toml +142 -0
- package/templates/pi/workpad.md +53 -0
- package/templates/project/java/Dockerfile +14 -0
- package/templates/project/java/README.md +40 -0
- package/templates/project/java/pom.xml +132 -0
- package/templates/project/typescript/Dockerfile +15 -0
- package/templates/project/typescript/README.md +29 -0
- package/templates/project/typescript/package.json +23 -0
- package/templates/project/typescript/tsconfig.json +21 -0
- package/templates/workflow.md +123 -0
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
# Python Code Patterns
|
|
2
|
+
|
|
3
|
+
> **Purpose:** Reusable Python patterns for Guardian projects.
|
|
4
|
+
> **Generic:** Adapt for your framework (FastAPI, Django, etc.).
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Error Handling
|
|
9
|
+
|
|
10
|
+
```python
|
|
11
|
+
# Custom exception classes
|
|
12
|
+
class ValidationError(Exception):
|
|
13
|
+
def __init__(self, message: str, field: str):
|
|
14
|
+
super().__init__(message)
|
|
15
|
+
self.field = field
|
|
16
|
+
|
|
17
|
+
class ConfigError(Exception):
|
|
18
|
+
pass
|
|
19
|
+
|
|
20
|
+
# Result type pattern (optional, for library code)
|
|
21
|
+
from dataclasses import dataclass
|
|
22
|
+
from typing import Generic, TypeVar, Union
|
|
23
|
+
|
|
24
|
+
T = TypeVar('T')
|
|
25
|
+
E = TypeVar('E')
|
|
26
|
+
|
|
27
|
+
@dataclass
|
|
28
|
+
class Ok(Generic[T]):
|
|
29
|
+
value: T
|
|
30
|
+
ok: bool = True
|
|
31
|
+
|
|
32
|
+
@dataclass
|
|
33
|
+
class Err(Generic[E]):
|
|
34
|
+
error: E
|
|
35
|
+
ok: bool = False
|
|
36
|
+
|
|
37
|
+
Result = Union[Ok[T], Err[E]]
|
|
38
|
+
|
|
39
|
+
def parse_config(input: str) -> Result[dict, ValidationError]:
|
|
40
|
+
try:
|
|
41
|
+
return Ok(json.loads(input))
|
|
42
|
+
except json.JSONDecodeError:
|
|
43
|
+
return Err(ValidationError("Invalid JSON", "config"))
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Tracing / Logging
|
|
49
|
+
|
|
50
|
+
```python
|
|
51
|
+
import logging
|
|
52
|
+
import structlog
|
|
53
|
+
|
|
54
|
+
# Structured logging
|
|
55
|
+
logger = structlog.get_logger()
|
|
56
|
+
|
|
57
|
+
def process_request(user_id: str, request_id: str):
|
|
58
|
+
logger.info("Processing request", user_id=user_id, request_id=request_id)
|
|
59
|
+
try:
|
|
60
|
+
result = do_work()
|
|
61
|
+
logger.info("Request complete", result=result)
|
|
62
|
+
except Exception as e:
|
|
63
|
+
logger.error("Request failed", error=str(e), exc_info=True)
|
|
64
|
+
raise
|
|
65
|
+
|
|
66
|
+
# Standard logging alternative
|
|
67
|
+
logging.basicConfig(
|
|
68
|
+
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
|
|
69
|
+
level=logging.INFO
|
|
70
|
+
)
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
---
|
|
74
|
+
|
|
75
|
+
## Cancellation / Cleanup
|
|
76
|
+
|
|
77
|
+
```python
|
|
78
|
+
import asyncio
|
|
79
|
+
from contextlib import asynccontextmanager
|
|
80
|
+
|
|
81
|
+
# Async cancellation
|
|
82
|
+
async def long_running_task(cancel_event: asyncio.Event):
|
|
83
|
+
while not cancel_event.is_set():
|
|
84
|
+
await do_work()
|
|
85
|
+
await asyncio.sleep(1)
|
|
86
|
+
|
|
87
|
+
# Context manager for cleanup
|
|
88
|
+
@asynccontextmanager
|
|
89
|
+
async def managed_resource():
|
|
90
|
+
resource = acquire_resource()
|
|
91
|
+
try:
|
|
92
|
+
yield resource
|
|
93
|
+
finally:
|
|
94
|
+
release_resource(resource)
|
|
95
|
+
|
|
96
|
+
# Usage
|
|
97
|
+
async def main():
|
|
98
|
+
cancel_event = asyncio.Event()
|
|
99
|
+
task = asyncio.create_task(long_running_task(cancel_event))
|
|
100
|
+
|
|
101
|
+
# Cancel after timeout
|
|
102
|
+
await asyncio.sleep(10)
|
|
103
|
+
cancel_event.set()
|
|
104
|
+
await task
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
## Atomic Writes
|
|
110
|
+
|
|
111
|
+
```python
|
|
112
|
+
import os
|
|
113
|
+
import tempfile
|
|
114
|
+
|
|
115
|
+
def atomic_write(filepath: str, content: str):
|
|
116
|
+
# Write to temp file in same directory
|
|
117
|
+
dir_path = os.path.dirname(filepath)
|
|
118
|
+
with tempfile.NamedTemporaryFile(
|
|
119
|
+
mode='w',
|
|
120
|
+
dir=dir_path,
|
|
121
|
+
delete=False,
|
|
122
|
+
suffix='.tmp'
|
|
123
|
+
) as tmp:
|
|
124
|
+
tmp.write(content)
|
|
125
|
+
tmp_path = tmp.name
|
|
126
|
+
|
|
127
|
+
# Atomic rename
|
|
128
|
+
os.replace(tmp_path, filepath)
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
---
|
|
132
|
+
|
|
133
|
+
## Async Patterns
|
|
134
|
+
|
|
135
|
+
```python
|
|
136
|
+
import asyncio
|
|
137
|
+
|
|
138
|
+
# Parallel execution
|
|
139
|
+
async def parallel_tasks():
|
|
140
|
+
results = await asyncio.gather(
|
|
141
|
+
task_a(),
|
|
142
|
+
task_b(),
|
|
143
|
+
task_c()
|
|
144
|
+
)
|
|
145
|
+
return results
|
|
146
|
+
|
|
147
|
+
# Concurrent limit
|
|
148
|
+
async def concurrent_limit(tasks: list, limit: int):
|
|
149
|
+
semaphore = asyncio.Semaphore(limit)
|
|
150
|
+
|
|
151
|
+
async def bounded_task(task):
|
|
152
|
+
async with semaphore:
|
|
153
|
+
return await task()
|
|
154
|
+
|
|
155
|
+
return await asyncio.gather(*[bounded_task(t) for t in tasks])
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## Testing
|
|
161
|
+
|
|
162
|
+
```python
|
|
163
|
+
# pytest patterns
|
|
164
|
+
import pytest
|
|
165
|
+
|
|
166
|
+
def test_parse():
|
|
167
|
+
result = parse("input")
|
|
168
|
+
assert result.ok == True
|
|
169
|
+
|
|
170
|
+
@pytest.mark.asyncio
|
|
171
|
+
async def test_async_flow():
|
|
172
|
+
result = await run_flow()
|
|
173
|
+
assert result is not None
|
|
174
|
+
|
|
175
|
+
# Mocking
|
|
176
|
+
from unittest.mock import Mock, patch
|
|
177
|
+
|
|
178
|
+
@patch('module.dependency')
|
|
179
|
+
def test_with_mock(mock_dep):
|
|
180
|
+
mock_dep.return_value = "mocked"
|
|
181
|
+
result = use_dependency()
|
|
182
|
+
assert result == "expected"
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
---
|
|
186
|
+
|
|
187
|
+
## Anti-Patterns (NEVER DO)
|
|
188
|
+
|
|
189
|
+
```python
|
|
190
|
+
# ❌ Bare except
|
|
191
|
+
try:
|
|
192
|
+
do_work()
|
|
193
|
+
except: # BAD - catches everything including KeyboardInterrupt
|
|
194
|
+
pass
|
|
195
|
+
|
|
196
|
+
# ✅ Specific exception
|
|
197
|
+
try:
|
|
198
|
+
do_work()
|
|
199
|
+
except ValueError as e:
|
|
200
|
+
logger.error("Validation failed", error=e)
|
|
201
|
+
except Exception as e:
|
|
202
|
+
logger.error("Unexpected error", error=e)
|
|
203
|
+
|
|
204
|
+
# ❌ Silent failures
|
|
205
|
+
def bad():
|
|
206
|
+
result = risky_operation()
|
|
207
|
+
if not result:
|
|
208
|
+
return None # BAD - no indication of failure
|
|
209
|
+
|
|
210
|
+
# ✅ Explicit error handling
|
|
211
|
+
def good():
|
|
212
|
+
result = risky_operation()
|
|
213
|
+
if not result.ok:
|
|
214
|
+
raise ValidationError(result.error)
|
|
215
|
+
return result.value
|
|
216
|
+
|
|
217
|
+
# ❌ Global state
|
|
218
|
+
config = {} # BAD - mutable global
|
|
219
|
+
|
|
220
|
+
# ✅ Encapsulated state
|
|
221
|
+
class Config:
|
|
222
|
+
def __init__(self):
|
|
223
|
+
self._data = {}
|
|
224
|
+
|
|
225
|
+
def get(self, key):
|
|
226
|
+
return self._data.get(key)
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
---
|
|
230
|
+
|
|
231
|
+
## Build Commands
|
|
232
|
+
|
|
233
|
+
```bash
|
|
234
|
+
# Install dependencies
|
|
235
|
+
poetry install
|
|
236
|
+
|
|
237
|
+
# Activate shell with project venv
|
|
238
|
+
poetry shell
|
|
239
|
+
|
|
240
|
+
# Run with poetry venv
|
|
241
|
+
poetry run archguard
|
|
242
|
+
|
|
243
|
+
# Test
|
|
244
|
+
poetry run pytest
|
|
245
|
+
|
|
246
|
+
# Test with coverage
|
|
247
|
+
poetry run pytest --cov=.
|
|
248
|
+
|
|
249
|
+
# Lint
|
|
250
|
+
poetry run ruff check .
|
|
251
|
+
|
|
252
|
+
# Format
|
|
253
|
+
poetry run ruff format .
|
|
254
|
+
|
|
255
|
+
# Type check
|
|
256
|
+
poetry run mypy .
|
|
257
|
+
|
|
258
|
+
# Security audit
|
|
259
|
+
poetry run pip-audit
|
|
260
|
+
|
|
261
|
+
# Build
|
|
262
|
+
poetry build
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
---
|
|
266
|
+
|
|
267
|
+
## Dependencies
|
|
268
|
+
|
|
269
|
+
```toml
|
|
270
|
+
# pyproject.toml — Poetry-based project
|
|
271
|
+
[tool.poetry]
|
|
272
|
+
name = "archguard"
|
|
273
|
+
version = "0.1.0"
|
|
274
|
+
description = "Engineering Change Intelligence Platform"
|
|
275
|
+
authors = ["Arman <arman@example.com>"]
|
|
276
|
+
readme = "README.md"
|
|
277
|
+
package-mode = true
|
|
278
|
+
|
|
279
|
+
[tool.poetry.dependencies]
|
|
280
|
+
python = "^3.12"
|
|
281
|
+
fastapi = "^0.115.0"
|
|
282
|
+
uvicorn = "^0.32.0"
|
|
283
|
+
pydantic = "^2.0.0"
|
|
284
|
+
structlog = "^24.0.0"
|
|
285
|
+
asyncpg = "^0.30.0"
|
|
286
|
+
httpx = "^0.27.0"
|
|
287
|
+
redis = "^5.0.0"
|
|
288
|
+
celery = "^5.4.0"
|
|
289
|
+
|
|
290
|
+
[tool.poetry.group.dev.dependencies]
|
|
291
|
+
pytest = "^8.0.0"
|
|
292
|
+
pytest-asyncio = "^0.24.0"
|
|
293
|
+
pytest-cov = "^6.0.0"
|
|
294
|
+
ruff = "^0.8.0"
|
|
295
|
+
mypy = "^1.0.0"
|
|
296
|
+
pip-audit = "^2.0.0"
|
|
297
|
+
|
|
298
|
+
[tool.poetry.scripts]
|
|
299
|
+
archguard = "archguard.main:main"
|
|
300
|
+
|
|
301
|
+
[build-system]
|
|
302
|
+
requires = ["poetry-core"]
|
|
303
|
+
build-backend = "poetry.core.masonry.api"
|
|
304
|
+
|
|
305
|
+
[tool.ruff]
|
|
306
|
+
target-version = "py312"
|
|
307
|
+
line-length = 88
|
|
308
|
+
|
|
309
|
+
[tool.mypy]
|
|
310
|
+
python_version = "3.12"
|
|
311
|
+
strict = true
|
|
312
|
+
```
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
# Rust Code Patterns
|
|
2
|
+
|
|
3
|
+
> **Purpose:** Reusable Rust patterns for Guardian projects.
|
|
4
|
+
> **Source:** Extracted from Rigorix framework.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Error Handling
|
|
9
|
+
|
|
10
|
+
```rust
|
|
11
|
+
// Use thiserror for all errors (never anyhow in library code)
|
|
12
|
+
use thiserror::Error;
|
|
13
|
+
|
|
14
|
+
#[derive(Error, Debug)]
|
|
15
|
+
pub enum MyError {
|
|
16
|
+
#[error("IO error: {0}")]
|
|
17
|
+
Io(#[from] std::io::Error),
|
|
18
|
+
|
|
19
|
+
#[error("Parse error at line {line}: {message}")]
|
|
20
|
+
Parse { line: usize, message: String },
|
|
21
|
+
|
|
22
|
+
#[error("Invalid configuration: {0}")]
|
|
23
|
+
Config(String),
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Automatic conversion with #[from]
|
|
27
|
+
fn read_file(path: &str) -> Result<String, MyError> {
|
|
28
|
+
std::fs::read_to_string(path)?; // Auto-converts io::Error → MyError
|
|
29
|
+
Ok(content)
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Tracing / Logging
|
|
36
|
+
|
|
37
|
+
```rust
|
|
38
|
+
use tracing::{instrument, info, warn, error};
|
|
39
|
+
|
|
40
|
+
// Add #[instrument] to public functions
|
|
41
|
+
#[instrument(skip(non_debug_param), fields(user_id = %user_id))]
|
|
42
|
+
pub async fn process_request(user_id: Uuid, non_debug_param: Vec<u8>) -> Result<()> {
|
|
43
|
+
info!("Processing request");
|
|
44
|
+
// ...
|
|
45
|
+
warn!("Something unusual happened");
|
|
46
|
+
// ...
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Cancellation / Cleanup
|
|
53
|
+
|
|
54
|
+
```rust
|
|
55
|
+
use tokio_util::sync::CancellationToken;
|
|
56
|
+
|
|
57
|
+
pub async fn long_running_task(cancel_token: CancellationToken) -> Result<()> {
|
|
58
|
+
loop {
|
|
59
|
+
// Check cancellation in loops
|
|
60
|
+
if cancel_token.is_cancelled() {
|
|
61
|
+
info!("Task cancelled, cleaning up");
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Do work
|
|
66
|
+
do_work()?;
|
|
67
|
+
|
|
68
|
+
// Sleep with cancellation awareness
|
|
69
|
+
tokio::select! {
|
|
70
|
+
_ = tokio::time::sleep(Duration::from_secs(1)) => {},
|
|
71
|
+
_ = cancel_token.cancelled() => break,
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
Ok(())
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## Atomic Writes
|
|
81
|
+
|
|
82
|
+
```rust
|
|
83
|
+
use std::fs;
|
|
84
|
+
use std::path::Path;
|
|
85
|
+
|
|
86
|
+
// Write-rename pattern for atomic file persistence
|
|
87
|
+
pub fn atomic_write(path: &Path, content: &str) -> std::io::Result<()> {
|
|
88
|
+
let temp_path = path.with_extension("tmp");
|
|
89
|
+
|
|
90
|
+
// Write to temp file
|
|
91
|
+
fs::write(&temp_path, content)?;
|
|
92
|
+
|
|
93
|
+
// Atomic rename (on POSIX systems)
|
|
94
|
+
fs::rename(&temp_path, path)?;
|
|
95
|
+
|
|
96
|
+
Ok(())
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## Async Patterns
|
|
103
|
+
|
|
104
|
+
```rust
|
|
105
|
+
// Use tokio for async runtime
|
|
106
|
+
use tokio::sync::{Mutex, RwLock};
|
|
107
|
+
|
|
108
|
+
// RwLock for read-heavy workloads
|
|
109
|
+
pub struct Cache {
|
|
110
|
+
data: RwLock<HashMap<String, Data>>,
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Mutex for write-heavy or complex state
|
|
114
|
+
pub struct StateMachine {
|
|
115
|
+
state: Mutex<State>,
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Prefer async-friendly types
|
|
119
|
+
// ✅ Use tokio::fs instead of std::fs in async context
|
|
120
|
+
// ❌ Never block in async context (no std::fs::read_to_string)
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
## Testing
|
|
126
|
+
|
|
127
|
+
```rust
|
|
128
|
+
// Unit tests inline
|
|
129
|
+
#[cfg(test)]
|
|
130
|
+
mod tests {
|
|
131
|
+
use super::*;
|
|
132
|
+
|
|
133
|
+
#[test]
|
|
134
|
+
fn test_parse() {
|
|
135
|
+
let result = parse("input");
|
|
136
|
+
assert!(result.is_ok());
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Integration tests in tests/ directory
|
|
141
|
+
// tests/integration_test.rs
|
|
142
|
+
use rigorix::*;
|
|
143
|
+
|
|
144
|
+
#[tokio::test]
|
|
145
|
+
async fn test_full_flow() {
|
|
146
|
+
let result = run_flow();
|
|
147
|
+
assert!(result.is_ok());
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## Anti-Patterns (NEVER DO)
|
|
154
|
+
|
|
155
|
+
```rust
|
|
156
|
+
// ❌ Using anyhow in library code
|
|
157
|
+
use anyhow::Result; // BAD
|
|
158
|
+
|
|
159
|
+
// ✅ Use thiserror for library errors
|
|
160
|
+
use thiserror::Error; // GOOD
|
|
161
|
+
|
|
162
|
+
// ❌ Blocking in async context
|
|
163
|
+
async fn bad() {
|
|
164
|
+
let data = std::fs::read_to_string("file"); // BAD - blocks
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// ✅ Use async-friendly APIs
|
|
168
|
+
async fn good() {
|
|
169
|
+
let data = tokio::fs::read_to_string("file").await; // GOOD
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// ❌ Unbounded channels
|
|
173
|
+
let (tx, rx) = mpsc::unbounded_channel(); // BAD
|
|
174
|
+
|
|
175
|
+
// ✅ Bounded channels with backpressure
|
|
176
|
+
let (tx, rx) = mpsc::channel(100); // GOOD
|
|
177
|
+
|
|
178
|
+
// ❌ unwrap() in production code
|
|
179
|
+
let value = result.unwrap(); // BAD
|
|
180
|
+
|
|
181
|
+
// ✅ Proper error handling
|
|
182
|
+
let value = result?; // GOOD
|
|
183
|
+
// Or with context
|
|
184
|
+
let value = result.map_err(|e| MyError::Context(e))?;
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
---
|
|
188
|
+
|
|
189
|
+
## Build Commands
|
|
190
|
+
|
|
191
|
+
```bash
|
|
192
|
+
# Build
|
|
193
|
+
cargo build
|
|
194
|
+
|
|
195
|
+
# Build release
|
|
196
|
+
cargo build --release
|
|
197
|
+
|
|
198
|
+
# Test
|
|
199
|
+
cargo test --all
|
|
200
|
+
|
|
201
|
+
# Test specific
|
|
202
|
+
cargo test --test integration_test
|
|
203
|
+
|
|
204
|
+
# Lint
|
|
205
|
+
cargo clippy -- -D warnings
|
|
206
|
+
|
|
207
|
+
# Format
|
|
208
|
+
cargo fmt --check
|
|
209
|
+
|
|
210
|
+
# Security audit
|
|
211
|
+
cargo audit
|
|
212
|
+
|
|
213
|
+
# Coverage
|
|
214
|
+
cargo tarpaulin --out Html
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
## Dependencies
|
|
220
|
+
|
|
221
|
+
```toml
|
|
222
|
+
# Cargo.toml standard deps
|
|
223
|
+
[dependencies]
|
|
224
|
+
tokio = { version = "1", features = ["full"] }
|
|
225
|
+
thiserror = "1"
|
|
226
|
+
tracing = "0.1"
|
|
227
|
+
tracing-subscriber = "0.3"
|
|
228
|
+
serde = { version = "1", features = ["derive"] }
|
|
229
|
+
|
|
230
|
+
[dev-dependencies]
|
|
231
|
+
tokio-test = "0.4"
|
|
232
|
+
```
|