invar-tools 1.2.0__py3-none-any.whl → 1.3.0__py3-none-any.whl
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.
- invar/__init__.py +1 -0
- invar/core/contracts.py +10 -10
- invar/core/entry_points.py +105 -32
- invar/core/extraction.py +5 -6
- invar/core/format_specs.py +1 -2
- invar/core/formatter.py +6 -7
- invar/core/hypothesis_strategies.py +5 -7
- invar/core/inspect.py +1 -1
- invar/core/lambda_helpers.py +3 -3
- invar/core/models.py +7 -1
- invar/core/must_use.py +2 -1
- invar/core/parser.py +7 -4
- invar/core/postcondition_scope.py +128 -0
- invar/core/property_gen.py +8 -5
- invar/core/purity.py +3 -3
- invar/core/purity_heuristics.py +5 -9
- invar/core/references.py +8 -6
- invar/core/review_trigger.py +78 -6
- invar/core/rule_meta.py +8 -0
- invar/core/rules.py +18 -19
- invar/core/shell_analysis.py +5 -10
- invar/core/shell_architecture.py +2 -2
- invar/core/strategies.py +7 -14
- invar/core/suggestions.py +86 -0
- invar/core/sync_helpers.py +238 -0
- invar/core/tautology.py +102 -37
- invar/core/template_parser.py +467 -0
- invar/core/timeout_inference.py +4 -7
- invar/core/utils.py +13 -15
- invar/core/verification_routing.py +4 -7
- invar/mcp/server.py +100 -17
- invar/shell/commands/__init__.py +11 -0
- invar/shell/{cli.py → commands/guard.py} +94 -14
- invar/shell/{init_cmd.py → commands/init.py} +179 -27
- invar/shell/commands/merge.py +256 -0
- invar/shell/commands/sync_self.py +113 -0
- invar/shell/commands/template_sync.py +366 -0
- invar/shell/commands/update.py +48 -0
- invar/shell/config.py +12 -24
- invar/shell/coverage.py +351 -0
- invar/shell/guard_helpers.py +38 -17
- invar/shell/guard_output.py +7 -1
- invar/shell/property_tests.py +58 -22
- invar/shell/prove/__init__.py +9 -0
- invar/shell/{prove.py → prove/crosshair.py} +40 -33
- invar/shell/{prove_fallback.py → prove/hypothesis.py} +12 -4
- invar/shell/subprocess_env.py +393 -0
- invar/shell/template_engine.py +345 -0
- invar/shell/templates.py +19 -0
- invar/shell/testing.py +71 -20
- invar/templates/CLAUDE.md.template +38 -17
- invar/templates/aider.conf.yml.template +2 -2
- invar/templates/commands/{review.md → audit.md} +20 -82
- invar/templates/commands/guard.md +77 -0
- invar/templates/config/CLAUDE.md.jinja +206 -0
- invar/templates/config/context.md.jinja +92 -0
- invar/templates/config/pre-commit.yaml.jinja +44 -0
- invar/templates/context.md.template +33 -0
- invar/templates/cursorrules.template +7 -4
- invar/templates/examples/README.md +2 -0
- invar/templates/examples/conftest.py +3 -0
- invar/templates/examples/contracts.py +5 -5
- invar/templates/examples/core_shell.py +11 -7
- invar/templates/examples/workflow.md +81 -0
- invar/templates/manifest.toml +137 -0
- invar/templates/{INVAR.md → protocol/INVAR.md} +10 -7
- invar/templates/skills/develop/SKILL.md.jinja +318 -0
- invar/templates/skills/investigate/SKILL.md.jinja +106 -0
- invar/templates/skills/propose/SKILL.md.jinja +104 -0
- invar/templates/skills/review/SKILL.md.jinja +125 -0
- {invar_tools-1.2.0.dist-info → invar_tools-1.3.0.dist-info}/METADATA +108 -118
- invar_tools-1.3.0.dist-info/RECORD +95 -0
- invar_tools-1.3.0.dist-info/entry_points.txt +2 -0
- invar/contracts.py +0 -152
- invar/decorators.py +0 -94
- invar/invariant.py +0 -58
- invar/resource.py +0 -99
- invar/shell/update_cmd.py +0 -193
- invar_tools-1.2.0.dist-info/RECORD +0 -77
- invar_tools-1.2.0.dist-info/entry_points.txt +0 -2
- /invar/shell/{mutate_cmd.py → commands/mutate.py} +0 -0
- /invar/shell/{perception.py → commands/perception.py} +0 -0
- /invar/shell/{test_cmd.py → commands/test.py} +0 -0
- /invar/shell/{prove_accept.py → prove/accept.py} +0 -0
- /invar/shell/{prove_cache.py → prove/cache.py} +0 -0
- {invar_tools-1.2.0.dist-info → invar_tools-1.3.0.dist-info}/WHEEL +0 -0
- {invar_tools-1.2.0.dist-info → invar_tools-1.3.0.dist-info}/licenses/LICENSE +0 -0
- {invar_tools-1.2.0.dist-info → invar_tools-1.3.0.dist-info}/licenses/LICENSE-GPL +0 -0
- {invar_tools-1.2.0.dist-info → invar_tools-1.3.0.dist-info}/licenses/NOTICE +0 -0
|
@@ -1,73 +1,14 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Audit
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
Before reviewing, determine the appropriate mode:
|
|
6
|
-
|
|
7
|
-
### Check for `review_suggested`
|
|
8
|
-
|
|
9
|
-
Look at your conversation history for recent `invar guard` output, or run:
|
|
10
|
-
```bash
|
|
11
|
-
invar guard --changed
|
|
12
|
-
```
|
|
13
|
-
|
|
14
|
-
Check if `review_suggested` warning is present:
|
|
15
|
-
```
|
|
16
|
-
WARNING: review_suggested - High escape hatch count: N @invar:allow markers
|
|
17
|
-
WARNING: review_suggested - Security-sensitive path detected
|
|
18
|
-
WARNING: review_suggested - Low contract coverage
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
### Select Mode
|
|
22
|
-
|
|
23
|
-
| Condition | Mode | Why |
|
|
24
|
-
|-----------|------|-----|
|
|
25
|
-
| `review_suggested` present | **Isolated** | Eliminates confirmation bias |
|
|
26
|
-
| No trigger | **Quick** | Faster, context preserved |
|
|
27
|
-
| User requests `--isolated` | **Isolated** | Explicit override |
|
|
28
|
-
| User requests `--quick` | **Quick** | Explicit override |
|
|
29
|
-
|
|
30
|
-
---
|
|
31
|
-
|
|
32
|
-
## Isolated Mode
|
|
33
|
-
|
|
34
|
-
**Use when:** `review_suggested` triggered, or user explicitly requests isolation.
|
|
35
|
-
|
|
36
|
-
Spawn an independent reviewer with fresh context using Task tool:
|
|
37
|
-
|
|
38
|
-
```
|
|
39
|
-
I'll spawn an independent reviewer to eliminate confirmation bias...
|
|
40
|
-
|
|
41
|
-
[Task tool call]
|
|
42
|
-
prompt: |
|
|
43
|
-
You are an adversarial code reviewer. Your job is to FIND PROBLEMS.
|
|
44
|
-
|
|
45
|
-
Review these files: {files_to_review}
|
|
46
|
-
|
|
47
|
-
Read .claude/commands/review.md for the full checklist, then:
|
|
48
|
-
1. Check contract semantic value (not just syntax)
|
|
49
|
-
2. Audit all escape hatches (@invar:allow)
|
|
50
|
-
3. Look for logic errors and edge cases
|
|
51
|
-
4. Check security if applicable
|
|
52
|
-
|
|
53
|
-
Report issues as CRITICAL/MAJOR/MINOR with file:line locations.
|
|
54
|
-
|
|
55
|
-
Your success is measured by problems found, not code approved.
|
|
56
|
-
|
|
57
|
-
subagent_type: "general-purpose"
|
|
58
|
-
```
|
|
59
|
-
|
|
60
|
-
After receiving the sub-agent's report, summarize findings for the user.
|
|
61
|
-
|
|
62
|
-
**Key:** The sub-agent has NO conversation history. It only sees the code.
|
|
3
|
+
Read-only code review. Reports issues without fixing them.
|
|
63
4
|
|
|
64
5
|
---
|
|
65
6
|
|
|
66
|
-
##
|
|
67
|
-
|
|
68
|
-
**Use when:** No `review_suggested` trigger, routine review needed.
|
|
7
|
+
## Behavior
|
|
69
8
|
|
|
70
|
-
|
|
9
|
+
1. Analyze code for issues (style, bugs, security, architecture)
|
|
10
|
+
2. Report findings with file:line references
|
|
11
|
+
3. **Do NOT make any changes** - report only
|
|
71
12
|
|
|
72
13
|
---
|
|
73
14
|
|
|
@@ -149,7 +90,7 @@ You ARE here to:
|
|
|
149
90
|
|
|
150
91
|
---
|
|
151
92
|
|
|
152
|
-
## Excluded (Covered by
|
|
93
|
+
## Excluded (Covered by Guard)
|
|
153
94
|
|
|
154
95
|
These are checked by Guard or linters - don't duplicate:
|
|
155
96
|
- Core/Shell separation → Guard (forbidden_import, impure_call)
|
|
@@ -157,7 +98,6 @@ These are checked by Guard or linters - don't duplicate:
|
|
|
157
98
|
- Missing contracts → Guard (missing_contract)
|
|
158
99
|
- File/function size limits → Guard (file_size, function_size)
|
|
159
100
|
- Entry point thickness → Guard (entry_point_too_thick)
|
|
160
|
-
- Magic numbers → Linters (ruff)
|
|
161
101
|
- Escape hatch count → Guard (review_suggested)
|
|
162
102
|
|
|
163
103
|
---
|
|
@@ -166,11 +106,11 @@ These are checked by Guard or linters - don't duplicate:
|
|
|
166
106
|
|
|
167
107
|
For each issue found, use severity levels:
|
|
168
108
|
|
|
169
|
-
| Severity | Meaning |
|
|
170
|
-
|
|
171
|
-
| **CRITICAL** | Must fix before completion |
|
|
172
|
-
| **MAJOR** | Fix or provide written justification |
|
|
173
|
-
| **MINOR** | Optional, can defer |
|
|
109
|
+
| Severity | Meaning |
|
|
110
|
+
|----------|---------|
|
|
111
|
+
| **CRITICAL** | Must fix before completion |
|
|
112
|
+
| **MAJOR** | Fix or provide written justification |
|
|
113
|
+
| **MINOR** | Optional, can defer |
|
|
174
114
|
|
|
175
115
|
```markdown
|
|
176
116
|
### [CRITICAL/MAJOR/MINOR] Issue Title
|
|
@@ -178,22 +118,20 @@ For each issue found, use severity levels:
|
|
|
178
118
|
**Location:** file.py:line_number
|
|
179
119
|
**Category:** contract_quality | logic_error | security | escape_hatch | code_smell
|
|
180
120
|
**Problem:** What's wrong
|
|
181
|
-
**Suggestion:** How to fix (
|
|
121
|
+
**Suggestion:** How to fix (but don't implement)
|
|
182
122
|
```
|
|
183
123
|
|
|
184
124
|
---
|
|
185
125
|
|
|
186
|
-
## Instructions
|
|
126
|
+
## Instructions
|
|
187
127
|
|
|
188
|
-
1.
|
|
189
|
-
2.
|
|
190
|
-
3.
|
|
191
|
-
4.
|
|
192
|
-
5.
|
|
193
|
-
6. Report with structured format above
|
|
194
|
-
7. Be thorough and adversarial
|
|
128
|
+
1. Run `invar guard --changed` to see current state
|
|
129
|
+
2. Go through each checklist category
|
|
130
|
+
3. For each issue, determine severity (CRITICAL/MAJOR/MINOR)
|
|
131
|
+
4. Report with structured format above
|
|
132
|
+
5. Be thorough and adversarial
|
|
195
133
|
|
|
196
|
-
**Remember:** You are READ-ONLY. Report issues, don't fix them
|
|
134
|
+
**Remember:** You are READ-ONLY. Report issues, don't fix them.
|
|
197
135
|
|
|
198
136
|
---
|
|
199
137
|
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
# Guard
|
|
2
|
+
|
|
3
|
+
Run Invar verification on the project and report results.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Behavior
|
|
8
|
+
|
|
9
|
+
Execute `invar_guard()` and report:
|
|
10
|
+
- Pass/fail status
|
|
11
|
+
- Error count with details
|
|
12
|
+
- Warning count with details
|
|
13
|
+
|
|
14
|
+
**Do NOT fix issues** - just report verification results.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## When to Use
|
|
19
|
+
|
|
20
|
+
- Quick verification check
|
|
21
|
+
- Before committing changes
|
|
22
|
+
- After pulling changes
|
|
23
|
+
- To see current project health
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Execution
|
|
28
|
+
|
|
29
|
+
Run verification:
|
|
30
|
+
|
|
31
|
+
```
|
|
32
|
+
invar_guard(changed=true)
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Or for full project verification:
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
invar_guard()
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
## Report Format
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
## Guard Results
|
|
47
|
+
|
|
48
|
+
**Status:** PASS / FAIL
|
|
49
|
+
**Errors:** N
|
|
50
|
+
**Warnings:** N
|
|
51
|
+
|
|
52
|
+
### Errors (if any)
|
|
53
|
+
|
|
54
|
+
| Rule | File | Line | Message |
|
|
55
|
+
|------|------|------|---------|
|
|
56
|
+
| missing_contract | src/foo.py | 42 | Function 'bar' has no @pre/@post |
|
|
57
|
+
|
|
58
|
+
### Warnings (if any)
|
|
59
|
+
|
|
60
|
+
| Rule | File | Line | Message |
|
|
61
|
+
|------|------|------|---------|
|
|
62
|
+
| function_size | src/baz.py | 15 | Function exceeds 50 lines |
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## Next Steps
|
|
68
|
+
|
|
69
|
+
After reporting results:
|
|
70
|
+
- If PASS: No action needed
|
|
71
|
+
- If FAIL: User decides whether to fix issues
|
|
72
|
+
|
|
73
|
+
**Remember:** You are READ-ONLY. Report results, don't fix them.
|
|
74
|
+
|
|
75
|
+
---
|
|
76
|
+
|
|
77
|
+
Now run verification on the current project.
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
<!--invar:managed version="{{ version }}"-->
|
|
2
|
+
# Project Development Guide
|
|
3
|
+
|
|
4
|
+
> **Protocol:** Follow [INVAR.md](./INVAR.md) — includes Check-In, USBV workflow, and Task Completion requirements.
|
|
5
|
+
|
|
6
|
+
## Check-In (DX-54)
|
|
7
|
+
|
|
8
|
+
Your first message MUST display:
|
|
9
|
+
|
|
10
|
+
```
|
|
11
|
+
✓ Check-In: [project] | [branch] | [clean/dirty]
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Actions:
|
|
15
|
+
1. Read `.invar/context.md` (Key Rules + Current State + Lessons Learned)
|
|
16
|
+
2. Show one-line status
|
|
17
|
+
|
|
18
|
+
Example:
|
|
19
|
+
```
|
|
20
|
+
✓ Check-In: MyProject | main | clean
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
**Do NOT execute guard or map at Check-In.**
|
|
24
|
+
Guard is for VALIDATE phase and Final only.
|
|
25
|
+
|
|
26
|
+
This is your sign-in. The user sees it immediately.
|
|
27
|
+
No visible check-in = Session not started.
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## Final
|
|
32
|
+
|
|
33
|
+
Your last message for an implementation task MUST display:
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
✓ Final: guard PASS | 0 errors, 2 warnings
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
{% if syntax == "mcp" -%}
|
|
40
|
+
Execute `invar_guard()` and show this one-line summary.
|
|
41
|
+
{% else -%}
|
|
42
|
+
Execute `invar guard` and show this one-line summary.
|
|
43
|
+
{% endif %}
|
|
44
|
+
|
|
45
|
+
This is your sign-out. Completes the Check-In/Final pair.
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## Project Structure
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
src/{project}/
|
|
53
|
+
├── core/ # Pure logic (@pre/@post, doctests, no I/O)
|
|
54
|
+
└── shell/ # I/O operations (Result[T, E] return type)
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
**Key insight:** Core receives data (strings), Shell handles I/O (paths, files).
|
|
58
|
+
|
|
59
|
+
## Quick Reference
|
|
60
|
+
|
|
61
|
+
| Zone | Requirements |
|
|
62
|
+
|------|-------------|
|
|
63
|
+
| Core | `@pre`/`@post` + doctests, pure (no I/O) |
|
|
64
|
+
| Shell | Returns `Result[T, E]` from `returns` library |
|
|
65
|
+
|
|
66
|
+
## Documentation Structure
|
|
67
|
+
|
|
68
|
+
| File | Owner | Edit? | Purpose |
|
|
69
|
+
|------|-------|-------|---------|
|
|
70
|
+
| INVAR.md | Invar | No | Protocol (`invar update` to sync) |
|
|
71
|
+
| CLAUDE.md | User | Yes | Project customization (this file) |
|
|
72
|
+
| .invar/context.md | User | Yes | Project state, lessons learned |
|
|
73
|
+
| .invar/examples/ | Invar | No | **Must read:** Core/Shell patterns, workflow |
|
|
74
|
+
|
|
75
|
+
## Visible Workflow (DX-30)
|
|
76
|
+
|
|
77
|
+
For complex tasks (3+ functions), show 3 checkpoints in TodoList:
|
|
78
|
+
|
|
79
|
+
```
|
|
80
|
+
□ [UNDERSTAND] Task description, codebase context, constraints
|
|
81
|
+
□ [SPECIFY] Contracts (@pre/@post) and design decomposition
|
|
82
|
+
□ [VALIDATE] Guard results, Review Gate status, integration status
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
**BUILD is internal work** — not shown in TodoList.
|
|
86
|
+
|
|
87
|
+
**Show contracts before code.** See `.invar/examples/workflow.md` for full example.
|
|
88
|
+
|
|
89
|
+
## Phase Visibility (DX-51)
|
|
90
|
+
|
|
91
|
+
Each USBV phase transition requires a visible header:
|
|
92
|
+
|
|
93
|
+
```
|
|
94
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
95
|
+
📍 /develop → SPECIFY (2/4)
|
|
96
|
+
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
**Three-layer visibility:**
|
|
100
|
+
- **Skill** (`/develop`) — Routing announcement
|
|
101
|
+
- **Phase** (`SPECIFY 2/4`) — Phase header (this section)
|
|
102
|
+
- **Tasks** — TodoWrite items
|
|
103
|
+
|
|
104
|
+
Phase headers are SEPARATE from TodoWrite. Phase = where you are; TodoWrite = what to do.
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## Context Management (DX-54)
|
|
109
|
+
|
|
110
|
+
Re-read `.invar/context.md` when:
|
|
111
|
+
1. Entering any workflow (/develop, /review, etc.)
|
|
112
|
+
2. Completing a TodoWrite task (before moving to next)
|
|
113
|
+
3. Conversation exceeds ~15-20 exchanges
|
|
114
|
+
4. Unsure about project rules or patterns
|
|
115
|
+
|
|
116
|
+
**Refresh is transparent** — do not announce "I'm refreshing context."
|
|
117
|
+
Only show routing announcements when entering workflows.
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## Commands (User-Invokable)
|
|
122
|
+
|
|
123
|
+
| Command | Purpose |
|
|
124
|
+
|---------|---------|
|
|
125
|
+
| `/audit` | Read-only code review (reports issues, no fixes) |
|
|
126
|
+
| `/guard` | Run Invar verification (reports results) |
|
|
127
|
+
|
|
128
|
+
## Skills (Agent-Invoked)
|
|
129
|
+
|
|
130
|
+
| Skill | Triggers | Purpose |
|
|
131
|
+
|-------|----------|---------|
|
|
132
|
+
| `/investigate` | "why", "explain", vague tasks | Research mode, no code changes |
|
|
133
|
+
| `/propose` | "should we", "compare" | Decision facilitation |
|
|
134
|
+
| `/develop` | "add", "fix", "implement" | USBV implementation workflow |
|
|
135
|
+
| `/review` | After /develop, `review_suggested` | Adversarial review with fix loop |
|
|
136
|
+
|
|
137
|
+
**Note:** Skills are invoked by agent based on context. Use `/audit` for user-initiated review.
|
|
138
|
+
|
|
139
|
+
Guard triggers `review_suggested` for: security-sensitive files, escape hatches >= 3, contract coverage < 50%.
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## Workflow Routing (MANDATORY)
|
|
144
|
+
|
|
145
|
+
When user message contains these triggers, you MUST invoke the corresponding skill:
|
|
146
|
+
|
|
147
|
+
| Trigger Words | Skill | Notes |
|
|
148
|
+
|---------------|-------|-------|
|
|
149
|
+
| "review", "review and fix" | `/review` | Adversarial review with fix loop |
|
|
150
|
+
| "implement", "add", "fix", "update" | `/develop` | Unless in review context |
|
|
151
|
+
| "why", "explain", "investigate" | `/investigate` | Research mode, no code changes |
|
|
152
|
+
| "compare", "should we", "design" | `/propose` | Decision facilitation |
|
|
153
|
+
|
|
154
|
+
**Violation check (before writing ANY code):**
|
|
155
|
+
- "Am I in a workflow?"
|
|
156
|
+
- "Did I invoke the correct skill?"
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## Routing Control (DX-42)
|
|
161
|
+
|
|
162
|
+
Agent announces routing decision before entering any workflow:
|
|
163
|
+
|
|
164
|
+
```
|
|
165
|
+
📍 Routing: /[skill] — [trigger or reason]
|
|
166
|
+
Task: [summary]
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
**User can redirect with natural language:**
|
|
170
|
+
- "wait" / "stop" — pause and ask for direction
|
|
171
|
+
- "just do it" — proceed with /develop
|
|
172
|
+
- "let's discuss" — switch to /propose
|
|
173
|
+
- "explain first" — switch to /investigate
|
|
174
|
+
|
|
175
|
+
**Simple task optimization:** For simple tasks (single file, clear target, <50 lines), agent may offer:
|
|
176
|
+
|
|
177
|
+
```
|
|
178
|
+
📊 Simple task. Auto-orchestrate? [Y/N]
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
- Y → Full cycle without intermediate confirmations
|
|
182
|
+
- N → Normal step-by-step workflow
|
|
183
|
+
|
|
184
|
+
**Auto-review (DX-41):** When Guard outputs `review_suggested`, agent automatically
|
|
185
|
+
enters /review. Say "skip" to bypass.
|
|
186
|
+
<!--/invar:managed-->
|
|
187
|
+
|
|
188
|
+
<!--invar:project-->
|
|
189
|
+
<!-- ========================================================================
|
|
190
|
+
PROJECT REGION - INVAR PROJECT ONLY
|
|
191
|
+
This section is populated by .invar/project-additions.md via sync-self.
|
|
192
|
+
For other projects, this region remains empty.
|
|
193
|
+
======================================================================== -->
|
|
194
|
+
<!--/invar:project-->
|
|
195
|
+
|
|
196
|
+
<!--invar:user-->
|
|
197
|
+
<!-- ========================================================================
|
|
198
|
+
USER REGION - EDITABLE
|
|
199
|
+
Add your team conventions and project-specific rules below.
|
|
200
|
+
This section is preserved across invar update and sync-self.
|
|
201
|
+
======================================================================== -->
|
|
202
|
+
<!--/invar:user-->
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
206
|
+
*Generated by `invar init` v{{ version }}. Customize the user section freely.*
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# Project Context
|
|
2
|
+
|
|
3
|
+
*Last updated: [DATE]*
|
|
4
|
+
|
|
5
|
+
## Current State
|
|
6
|
+
|
|
7
|
+
- Phase: [current development phase]
|
|
8
|
+
- Working on: [current task or feature]
|
|
9
|
+
- Blockers: None
|
|
10
|
+
|
|
11
|
+
## Key Rules (Quick Reference)
|
|
12
|
+
|
|
13
|
+
<!-- DX-54: Rules summary for long conversation resilience -->
|
|
14
|
+
|
|
15
|
+
### Core/Shell Separation
|
|
16
|
+
- **Core** (`**/core/**`): @pre/@post + doctests, NO I/O imports
|
|
17
|
+
- **Shell** (`**/shell/**`): Result[T, E] return type
|
|
18
|
+
|
|
19
|
+
### USBV Workflow
|
|
20
|
+
1. Understand → 2. Specify (contracts first) → 3. Build → 4. Validate
|
|
21
|
+
|
|
22
|
+
### Verification
|
|
23
|
+
{% if syntax == "mcp" -%}
|
|
24
|
+
- `invar_guard()` = static + doctests + CrossHair + Hypothesis
|
|
25
|
+
{% else -%}
|
|
26
|
+
- `invar guard` = static + doctests + CrossHair + Hypothesis
|
|
27
|
+
{% endif -%}
|
|
28
|
+
- Final must show: `✓ Final: guard PASS | ...`
|
|
29
|
+
|
|
30
|
+
## Self-Reminder
|
|
31
|
+
|
|
32
|
+
<!-- DX-54: AI should re-read this file periodically -->
|
|
33
|
+
|
|
34
|
+
**When to re-read this file:**
|
|
35
|
+
- Starting a new task
|
|
36
|
+
- Completing a task (before moving to next)
|
|
37
|
+
- Conversation has been going on for a while (~15-20 exchanges)
|
|
38
|
+
- Unsure about project rules or patterns
|
|
39
|
+
|
|
40
|
+
**Quick rule check:**
|
|
41
|
+
- Am I in Core or Shell?
|
|
42
|
+
- Do I have @pre/@post contracts?
|
|
43
|
+
- Am I following USBV workflow?
|
|
44
|
+
- Did I run guard before claiming "done"?
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Recent Decisions
|
|
49
|
+
|
|
50
|
+
1. [Decision summary] - [Brief rationale]
|
|
51
|
+
|
|
52
|
+
## Lessons Learned
|
|
53
|
+
|
|
54
|
+
1. [Pitfall or issue] → [Solution or workaround]
|
|
55
|
+
|
|
56
|
+
## Documentation Structure
|
|
57
|
+
|
|
58
|
+
| File | Owner | Edit? |
|
|
59
|
+
|------|-------|-------|
|
|
60
|
+
| INVAR.md | Invar | No — use `invar update` |
|
|
61
|
+
| CLAUDE.md | User | Yes |
|
|
62
|
+
| .invar/context.md | User | Yes (this file) |
|
|
63
|
+
| .invar/examples/ | Invar | No |
|
|
64
|
+
|
|
65
|
+
**Decision rule:** Is this Invar protocol or project-specific?
|
|
66
|
+
- Protocol content → Already in INVAR.md, don't duplicate
|
|
67
|
+
- Project-specific → Add to CLAUDE.md or here
|
|
68
|
+
|
|
69
|
+
## Technical Debt
|
|
70
|
+
|
|
71
|
+
{% if syntax == "mcp" -%}
|
|
72
|
+
*Run `invar_guard()` to check current status.*
|
|
73
|
+
{% else -%}
|
|
74
|
+
*Run `invar guard` to check current status.*
|
|
75
|
+
{% endif %}
|
|
76
|
+
|
|
77
|
+
| File | Warning | Priority |
|
|
78
|
+
|------|---------|----------|
|
|
79
|
+
| (none) | — | — |
|
|
80
|
+
|
|
81
|
+
## Key Files
|
|
82
|
+
|
|
83
|
+
| File | Purpose |
|
|
84
|
+
|------|---------|
|
|
85
|
+
| INVAR.md | Protocol reference (Invar-managed) |
|
|
86
|
+
| CLAUDE.md | Project guide (customize freely) |
|
|
87
|
+
| src/core/ | Pure business logic |
|
|
88
|
+
| src/shell/ | I/O adapters |
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
*Update this file when: completing major tasks, making design decisions, discovering pitfalls.*
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Invar Pre-commit Hooks v{{ version }}
|
|
2
|
+
# Install: pre-commit install
|
|
3
|
+
#
|
|
4
|
+
# Default runs full verification (static + doctests + CrossHair + Hypothesis).
|
|
5
|
+
# Incremental mode makes this fast: ~5s first commit, ~2s subsequent (cached).
|
|
6
|
+
#
|
|
7
|
+
# Smart Guard: Detects rule-affecting file changes and runs full guard when needed.
|
|
8
|
+
# Structure Protection: Warns if INVAR.md is modified directly.
|
|
9
|
+
|
|
10
|
+
repos:
|
|
11
|
+
- repo: local
|
|
12
|
+
hooks:
|
|
13
|
+
# Warn if INVAR.md is modified directly (use --no-verify if intentional)
|
|
14
|
+
- id: invar-md-protected
|
|
15
|
+
name: INVAR.md Protection
|
|
16
|
+
entry: bash -c 'if git diff --cached --name-only | grep -q "^INVAR.md$"; then echo "Warning - INVAR.md was modified directly. Use git commit --no-verify if intentional."; exit 1; fi'
|
|
17
|
+
language: system
|
|
18
|
+
pass_filenames: false
|
|
19
|
+
stages: [pre-commit]
|
|
20
|
+
|
|
21
|
+
# Invar Guard (full verification by default)
|
|
22
|
+
# Uses incremental mode: only verifies changed files, caches results
|
|
23
|
+
# Smart mode: runs full guard when rule files change, --changed otherwise
|
|
24
|
+
- id: invar-guard
|
|
25
|
+
name: Invar Guard
|
|
26
|
+
entry: bash -c '
|
|
27
|
+
RULE_FILES="rule_meta.py rules.py contracts.py purity.py pyproject.toml"
|
|
28
|
+
STAGED=$(git diff --cached --name-only)
|
|
29
|
+
FULL=false
|
|
30
|
+
for f in $RULE_FILES; do
|
|
31
|
+
if echo "$STAGED" | grep -q "$f"; then FULL=true; break; fi
|
|
32
|
+
done
|
|
33
|
+
if [ "$FULL" = true ]; then
|
|
34
|
+
echo "⚠️ Rule change detected - running FULL guard"
|
|
35
|
+
invar guard
|
|
36
|
+
else
|
|
37
|
+
invar guard --changed
|
|
38
|
+
fi
|
|
39
|
+
'
|
|
40
|
+
language: python
|
|
41
|
+
additional_dependencies: ['invar-tools']
|
|
42
|
+
pass_filenames: false
|
|
43
|
+
stages: [pre-commit]
|
|
44
|
+
types: [python]
|
|
@@ -8,6 +8,39 @@
|
|
|
8
8
|
- Working on: [current task or feature]
|
|
9
9
|
- Blockers: None
|
|
10
10
|
|
|
11
|
+
## Key Rules (Quick Reference)
|
|
12
|
+
|
|
13
|
+
<!-- DX-54: Rules summary for long conversation resilience -->
|
|
14
|
+
|
|
15
|
+
### Core/Shell Separation
|
|
16
|
+
- **Core** (`**/core/**`): @pre/@post + doctests, NO I/O imports
|
|
17
|
+
- **Shell** (`**/shell/**`): Result[T, E] return type
|
|
18
|
+
|
|
19
|
+
### USBV Workflow
|
|
20
|
+
1. Understand → 2. Specify (contracts first) → 3. Build → 4. Validate
|
|
21
|
+
|
|
22
|
+
### Verification
|
|
23
|
+
- `invar guard` = static + doctests + CrossHair + Hypothesis
|
|
24
|
+
- Final must show: `✓ Final: guard PASS | ...`
|
|
25
|
+
|
|
26
|
+
## Self-Reminder
|
|
27
|
+
|
|
28
|
+
<!-- DX-54: AI should re-read this file periodically -->
|
|
29
|
+
|
|
30
|
+
**When to re-read this file:**
|
|
31
|
+
- Starting a new task
|
|
32
|
+
- Completing a task (before moving to next)
|
|
33
|
+
- Conversation has been going on for a while (~15-20 exchanges)
|
|
34
|
+
- Unsure about project rules or patterns
|
|
35
|
+
|
|
36
|
+
**Quick rule check:**
|
|
37
|
+
- Am I in Core or Shell?
|
|
38
|
+
- Do I have @pre/@post contracts?
|
|
39
|
+
- Am I following USBV workflow?
|
|
40
|
+
- Did I run guard before claiming "done"?
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
11
44
|
## Recent Decisions
|
|
12
45
|
|
|
13
46
|
1. [Decision summary] - [Brief rationale]
|
|
@@ -7,16 +7,19 @@ Follow the Invar Protocol in INVAR.md — includes Check-In, USBV workflow, and
|
|
|
7
7
|
Your first message MUST display:
|
|
8
8
|
|
|
9
9
|
```
|
|
10
|
-
✓ Check-In:
|
|
10
|
+
✓ Check-In: [project] | [branch] | [clean/dirty]
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
|
|
13
|
+
Actions:
|
|
14
|
+
1. Read `.invar/context.md` (Key Rules + Current State + Lessons Learned)
|
|
15
|
+
2. Show one-line status
|
|
16
|
+
|
|
17
|
+
**Do NOT execute guard or map at Check-In.**
|
|
18
|
+
Guard is for VALIDATE phase and Final only.
|
|
14
19
|
|
|
15
20
|
This is your sign-in. The user sees it immediately.
|
|
16
21
|
No visible check-in = Session not started.
|
|
17
22
|
|
|
18
|
-
Then read `.invar/context.md` for project state and lessons learned.
|
|
19
|
-
|
|
20
23
|
## Final
|
|
21
24
|
|
|
22
25
|
Your last message for an implementation task MUST display:
|
|
@@ -8,6 +8,7 @@ Reference examples for the Invar Protocol. These are managed by Invar.
|
|
|
8
8
|
|------|---------|
|
|
9
9
|
| [contracts.py](contracts.py) | @pre/@post patterns, doctest best practices |
|
|
10
10
|
| [core_shell.py](core_shell.py) | Core/Shell separation patterns |
|
|
11
|
+
| [workflow.md](workflow.md) | Visible USBV workflow example |
|
|
11
12
|
|
|
12
13
|
## Usage
|
|
13
14
|
|
|
@@ -15,6 +16,7 @@ Read these when you need:
|
|
|
15
16
|
- Contract pattern reference
|
|
16
17
|
- Core vs Shell decision guidance
|
|
17
18
|
- Doctest formatting examples
|
|
19
|
+
- USBV workflow example
|
|
18
20
|
|
|
19
21
|
---
|
|
20
22
|
|
|
@@ -5,9 +5,9 @@ Reference patterns for @pre/@post contracts and doctests.
|
|
|
5
5
|
Managed by Invar - do not edit directly.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
-
#
|
|
9
|
-
#
|
|
10
|
-
from
|
|
8
|
+
# For lambda-based contracts, use deal directly
|
|
9
|
+
# invar_runtime.pre/post are for Contract objects (NonEmpty, IsInstance, etc.)
|
|
10
|
+
from deal import post, pre
|
|
11
11
|
|
|
12
12
|
# =============================================================================
|
|
13
13
|
# GOOD: Complete Contract
|
|
@@ -56,8 +56,8 @@ def average(items: list[float]) -> float:
|
|
|
56
56
|
# =============================================================================
|
|
57
57
|
|
|
58
58
|
|
|
59
|
-
@pre(lambda data:
|
|
60
|
-
@post(lambda result:
|
|
59
|
+
@pre(lambda data: len(data) > 0) # Non-empty input (type is in annotation)
|
|
60
|
+
@post(lambda result: len(result) > 0) # Preserves non-emptiness
|
|
61
61
|
def normalize_keys(data: dict[str, int]) -> dict[str, int]:
|
|
62
62
|
"""
|
|
63
63
|
Lowercase all keys.
|