invar-tools 1.8.0__py3-none-any.whl → 1.11.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.
Files changed (117) hide show
  1. invar/__init__.py +8 -0
  2. invar/core/doc_edit.py +187 -0
  3. invar/core/doc_parser.py +563 -0
  4. invar/core/language.py +88 -0
  5. invar/core/models.py +106 -0
  6. invar/core/patterns/detector.py +6 -1
  7. invar/core/patterns/p0_exhaustive.py +15 -3
  8. invar/core/patterns/p0_literal.py +15 -3
  9. invar/core/patterns/p0_newtype.py +15 -3
  10. invar/core/patterns/p0_nonempty.py +15 -3
  11. invar/core/patterns/p0_validation.py +15 -3
  12. invar/core/patterns/registry.py +5 -1
  13. invar/core/patterns/types.py +5 -1
  14. invar/core/property_gen.py +4 -0
  15. invar/core/rules.py +84 -18
  16. invar/core/sync_helpers.py +27 -1
  17. invar/core/ts_parsers.py +286 -0
  18. invar/core/ts_sig_parser.py +310 -0
  19. invar/mcp/handlers.py +408 -0
  20. invar/mcp/server.py +288 -143
  21. invar/node_tools/MANIFEST +7 -0
  22. invar/node_tools/__init__.py +51 -0
  23. invar/node_tools/fc-runner/cli.js +77 -0
  24. invar/node_tools/quick-check/cli.js +28 -0
  25. invar/node_tools/ts-analyzer/cli.js +480 -0
  26. invar/shell/claude_hooks.py +35 -12
  27. invar/shell/commands/doc.py +409 -0
  28. invar/shell/commands/guard.py +41 -1
  29. invar/shell/commands/init.py +154 -16
  30. invar/shell/commands/perception.py +157 -33
  31. invar/shell/commands/skill.py +187 -0
  32. invar/shell/commands/template_sync.py +65 -13
  33. invar/shell/commands/uninstall.py +60 -12
  34. invar/shell/commands/update.py +6 -14
  35. invar/shell/contract_coverage.py +1 -0
  36. invar/shell/doc_tools.py +459 -0
  37. invar/shell/fs.py +67 -13
  38. invar/shell/pi_hooks.py +6 -0
  39. invar/shell/prove/crosshair.py +3 -0
  40. invar/shell/prove/guard_ts.py +902 -0
  41. invar/shell/skill_manager.py +355 -0
  42. invar/shell/template_engine.py +28 -4
  43. invar/shell/templates.py +4 -4
  44. invar/templates/claude-md/python/critical-rules.md +33 -0
  45. invar/templates/claude-md/python/quick-reference.md +24 -0
  46. invar/templates/claude-md/typescript/critical-rules.md +40 -0
  47. invar/templates/claude-md/typescript/quick-reference.md +24 -0
  48. invar/templates/claude-md/universal/check-in.md +25 -0
  49. invar/templates/claude-md/universal/skills.md +73 -0
  50. invar/templates/claude-md/universal/workflow.md +55 -0
  51. invar/templates/commands/{audit.md → audit.md.jinja} +18 -1
  52. invar/templates/config/AGENT.md.jinja +58 -0
  53. invar/templates/config/CLAUDE.md.jinja +16 -209
  54. invar/templates/config/context.md.jinja +19 -0
  55. invar/templates/examples/{README.md → python/README.md} +2 -0
  56. invar/templates/examples/{conftest.py → python/conftest.py} +1 -1
  57. invar/templates/examples/{contracts.py → python/contracts.py} +81 -4
  58. invar/templates/examples/python/core_shell.py +227 -0
  59. invar/templates/examples/python/functional.py +613 -0
  60. invar/templates/examples/typescript/README.md +31 -0
  61. invar/templates/examples/typescript/contracts.ts +163 -0
  62. invar/templates/examples/typescript/core_shell.ts +374 -0
  63. invar/templates/examples/typescript/functional.ts +601 -0
  64. invar/templates/examples/typescript/workflow.md +95 -0
  65. invar/templates/hooks/PostToolUse.sh.jinja +10 -1
  66. invar/templates/hooks/PreToolUse.sh.jinja +38 -0
  67. invar/templates/hooks/Stop.sh.jinja +1 -1
  68. invar/templates/hooks/UserPromptSubmit.sh.jinja +7 -0
  69. invar/templates/hooks/pi/invar.ts.jinja +9 -0
  70. invar/templates/manifest.toml +7 -6
  71. invar/templates/onboard/assessment.md.jinja +214 -0
  72. invar/templates/onboard/patterns/python.md +347 -0
  73. invar/templates/onboard/patterns/typescript.md +452 -0
  74. invar/templates/onboard/roadmap.md.jinja +168 -0
  75. invar/templates/protocol/INVAR.md.jinja +51 -0
  76. invar/templates/protocol/python/architecture-examples.md +41 -0
  77. invar/templates/protocol/python/contracts-syntax.md +56 -0
  78. invar/templates/protocol/python/markers.md +44 -0
  79. invar/templates/protocol/python/tools.md +24 -0
  80. invar/templates/protocol/python/troubleshooting.md +38 -0
  81. invar/templates/protocol/typescript/architecture-examples.md +52 -0
  82. invar/templates/protocol/typescript/contracts-syntax.md +73 -0
  83. invar/templates/protocol/typescript/markers.md +48 -0
  84. invar/templates/protocol/typescript/tools.md +65 -0
  85. invar/templates/protocol/typescript/troubleshooting.md +104 -0
  86. invar/templates/protocol/universal/architecture.md +36 -0
  87. invar/templates/protocol/universal/completion.md +14 -0
  88. invar/templates/protocol/universal/contracts-concept.md +37 -0
  89. invar/templates/protocol/universal/header.md +17 -0
  90. invar/templates/protocol/universal/session.md +17 -0
  91. invar/templates/protocol/universal/six-laws.md +10 -0
  92. invar/templates/protocol/universal/usbv.md +14 -0
  93. invar/templates/protocol/universal/visible-workflow.md +25 -0
  94. invar/templates/skills/develop/SKILL.md.jinja +85 -3
  95. invar/templates/skills/extensions/_registry.yaml +93 -0
  96. invar/templates/skills/extensions/acceptance/SKILL.md +383 -0
  97. invar/templates/skills/extensions/invar-onboard/SKILL.md +448 -0
  98. invar/templates/skills/extensions/invar-onboard/patterns/python.md +347 -0
  99. invar/templates/skills/extensions/invar-onboard/patterns/typescript.md +452 -0
  100. invar/templates/skills/extensions/invar-onboard/templates/assessment.md.jinja +214 -0
  101. invar/templates/skills/extensions/invar-onboard/templates/roadmap.md.jinja +168 -0
  102. invar/templates/skills/extensions/security/SKILL.md +382 -0
  103. invar/templates/skills/extensions/security/patterns/_common.yaml +126 -0
  104. invar/templates/skills/extensions/security/patterns/python.yaml +155 -0
  105. invar/templates/skills/extensions/security/patterns/typescript.yaml +194 -0
  106. invar/templates/skills/review/SKILL.md.jinja +220 -248
  107. {invar_tools-1.8.0.dist-info → invar_tools-1.11.0.dist-info}/METADATA +336 -12
  108. invar_tools-1.11.0.dist-info/RECORD +178 -0
  109. invar/templates/examples/core_shell.py +0 -127
  110. invar/templates/protocol/INVAR.md +0 -310
  111. invar_tools-1.8.0.dist-info/RECORD +0 -116
  112. /invar/templates/examples/{workflow.md → python/workflow.md} +0 -0
  113. {invar_tools-1.8.0.dist-info → invar_tools-1.11.0.dist-info}/WHEEL +0 -0
  114. {invar_tools-1.8.0.dist-info → invar_tools-1.11.0.dist-info}/entry_points.txt +0 -0
  115. {invar_tools-1.8.0.dist-info → invar_tools-1.11.0.dist-info}/licenses/LICENSE +0 -0
  116. {invar_tools-1.8.0.dist-info → invar_tools-1.11.0.dist-info}/licenses/LICENSE-GPL +0 -0
  117. {invar_tools-1.8.0.dist-info → invar_tools-1.11.0.dist-info}/licenses/NOTICE +0 -0
@@ -0,0 +1,55 @@
1
+ ## Documentation Structure
2
+
3
+ | File | Owner | Edit? | Purpose |
4
+ |------|-------|-------|---------|
5
+ | INVAR.md | Invar | No | Protocol (`invar update` to sync) |
6
+ | CLAUDE.md | User | Yes | Project customization (this file) |
7
+ | .invar/context.md | User | Yes | Project state, lessons learned |
8
+ | .invar/project-additions.md | User | Yes | Project rules → injected into CLAUDE.md |
9
+ | .invar/examples/ | Invar | No | **Must read:** Core/Shell patterns, workflow |
10
+
11
+ > **Before writing code:** Check Task Router in `.invar/context.md`
12
+
13
+ ## Visible Workflow (DX-30)
14
+
15
+ For complex tasks (3+ functions), show 3 checkpoints in TodoList:
16
+
17
+ ```
18
+ □ [UNDERSTAND] Task description, codebase context, constraints
19
+ □ [SPECIFY] Contracts and design decomposition
20
+ □ [VALIDATE] Guard results, Review Gate status, integration status
21
+ ```
22
+
23
+ **BUILD is internal work** — not shown in TodoList.
24
+
25
+ **Show contracts before code.** See `.invar/examples/workflow.md` for full example.
26
+
27
+ ## Phase Visibility (DX-51)
28
+
29
+ Each USBV phase transition requires a visible header:
30
+
31
+ ```
32
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
33
+ 📍 /develop → SPECIFY (2/4)
34
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
35
+ ```
36
+
37
+ **Three-layer visibility:**
38
+ - **Skill** (`/develop`) — Routing announcement
39
+ - **Phase** (`SPECIFY 2/4`) — Phase header (this section)
40
+ - **Tasks** — TodoWrite items
41
+
42
+ Phase headers are SEPARATE from TodoWrite. Phase = where you are; TodoWrite = what to do.
43
+
44
+ ---
45
+
46
+ ## Context Management (DX-54)
47
+
48
+ Re-read `.invar/context.md` when:
49
+ 1. Entering any workflow (/develop, /review, etc.)
50
+ 2. Completing a TodoWrite task (before moving to next)
51
+ 3. Conversation exceeds ~15-20 exchanges
52
+ 4. Unsure about project rules or patterns
53
+
54
+ **Refresh is transparent** — do not announce "I'm refreshing context."
55
+ Only show routing announcements when entering workflows.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  _invar:
3
- version: "5.0"
3
+ version: "{{ version }}"
4
4
  type: command
5
5
  ---
6
6
 
@@ -51,12 +51,21 @@ You ARE here to:
51
51
  > **Principle:** Only items requiring semantic judgment. Mechanical checks are excluded (see bottom).
52
52
 
53
53
  ### A. Contract Semantic Value
54
+ {% if language == "python" %}
54
55
  - [ ] Does @pre constrain inputs beyond type checking?
55
56
  - Bad: `@pre(lambda x: isinstance(x, int))`
56
57
  - Good: `@pre(lambda x: x > 0 and x < MAX_VALUE)`
57
58
  - [ ] Does @post verify meaningful output properties?
58
59
  - Bad: `@post(lambda result: result is not None)`
59
60
  - Good: `@post(lambda result: len(result) == len(input))`
61
+ {% elif language == "typescript" %}
62
+ - [ ] Does Zod schema constrain inputs beyond type checking?
63
+ - Bad: `z.number()` (type only)
64
+ - Good: `z.number().positive().max(MAX_VALUE)` (semantic constraints)
65
+ - [ ] Does output schema verify meaningful properties?
66
+ - Bad: `z.string()` (type only)
67
+ - Good: `z.string().min(1).max(100)` (semantic constraints)
68
+ {% endif %}
60
69
  - [ ] Could someone implement correctly from contracts alone?
61
70
  - [ ] Are boundary conditions explicit in contracts?
62
71
 
@@ -100,7 +109,11 @@ You ARE here to:
100
109
 
101
110
  These are checked by Guard or linters - don't duplicate:
102
111
  - Core/Shell separation → Guard (forbidden_import, impure_call)
112
+ {% if language == "python" -%}
103
113
  - Shell returns Result[T,E] → Guard (shell_result)
114
+ {% elif language == "typescript" -%}
115
+ - Shell returns Result<T,E> → Guard (shell_result)
116
+ {% endif -%}
104
117
  - Missing contracts → Guard (missing_contract)
105
118
  - File/function size limits → Guard (file_size, function_size)
106
119
  - Entry point thickness → Guard (entry_point_too_thick)
@@ -121,7 +134,11 @@ For each issue found, use severity levels:
121
134
  ```markdown
122
135
  ### [CRITICAL/MAJOR/MINOR] Issue Title
123
136
 
137
+ {% if language == "python" -%}
124
138
  **Location:** file.py:line_number
139
+ {% elif language == "typescript" -%}
140
+ **Location:** file.ts:line_number
141
+ {% endif -%}
125
142
  **Category:** contract_quality | logic_error | security | escape_hatch | code_smell
126
143
  **Problem:** What's wrong
127
144
  **Suggestion:** How to fix (but don't implement)
@@ -8,12 +8,18 @@
8
8
  {% else -%}
9
9
  | **Verify** | `invar guard` — NOT pytest, NOT crosshair |
10
10
  {% endif -%}
11
+ {% if language == "python" -%}
11
12
  | **Core** | `@pre/@post` + doctests, NO I/O imports |
12
13
  | **Shell** | Returns `Result[T, E]` from `returns` library |
14
+ {% elif language == "typescript" -%}
15
+ | **Core** | Zod schemas + JSDoc examples, NO I/O imports |
16
+ | **Shell** | Returns `Result<T, E>` from `neverthrow` library |
17
+ {% endif -%}
13
18
  | **Flow** | USBV: Understand → Specify → Build → Validate |
14
19
 
15
20
  ### Contract Rules (CRITICAL)
16
21
 
22
+ {% if language == "python" -%}
17
23
  ```python
18
24
  # ❌ WRONG: Lambda must include ALL parameters
19
25
  @pre(lambda x: x >= 0)
@@ -29,6 +35,21 @@ def calc(x: int, y: int = 0): ...
29
35
  # ✅ CORRECT: @post only sees 'result'
30
36
  @post(lambda result: result >= 0)
31
37
  ```
38
+ {% elif language == "typescript" -%}
39
+ ```typescript
40
+ // ❌ WRONG: Type-only validation (no semantic value)
41
+ const Input = z.number();
42
+
43
+ // ✅ CORRECT: Semantic constraints
44
+ const Input = z.number().nonnegative().max(100);
45
+
46
+ // ❌ WRONG: Output schema cannot reference input
47
+ const Output = z.number().min(x); // 'x' not available!
48
+
49
+ // ✅ CORRECT: Output schema only validates result
50
+ const Output = z.number().nonnegative();
51
+ ```
52
+ {% endif -%}
32
53
 
33
54
  <!--/invar:critical-->
34
55
 
@@ -67,11 +88,19 @@ This is your sign-out. Completes the Check-In/Final pair.
67
88
 
68
89
  ## Project Structure
69
90
 
91
+ {% if language == "python" -%}
70
92
  ```
71
93
  src/{project}/
72
94
  ├── core/ # Pure logic (@pre/@post, doctests, no I/O)
73
95
  └── shell/ # I/O operations (Result[T, E] return type)
74
96
  ```
97
+ {% elif language == "typescript" -%}
98
+ ```
99
+ src/
100
+ ├── core/ # Pure logic (Zod schemas, JSDoc examples, no I/O)
101
+ └── shell/ # I/O operations (Result<T, E> return type)
102
+ ```
103
+ {% endif -%}
75
104
 
76
105
  **Key insight:** Core receives data (strings), Shell handles I/O (paths, files).
77
106
 
@@ -79,8 +108,13 @@ src/{project}/
79
108
 
80
109
  | Zone | Requirements |
81
110
  |------|-------------|
111
+ {% if language == "python" -%}
82
112
  | Core | `@pre`/`@post` + doctests, pure (no I/O) |
83
113
  | Shell | Returns `Result[T, E]` from `returns` library |
114
+ {% elif language == "typescript" -%}
115
+ | Core | Zod schemas + JSDoc examples, pure (no I/O) |
116
+ | Shell | Returns `Result<T, E>` from `neverthrow` library |
117
+ {% endif -%}
84
118
 
85
119
  ### Core vs Shell (Edge Cases)
86
120
 
@@ -118,10 +152,16 @@ For complex tasks (3+ functions), follow these phases:
118
152
 
119
153
  ### 2. SPECIFY
120
154
 
155
+ {% if language == "python" -%}
121
156
  - **Contracts FIRST:** Write `@pre`/`@post` before implementation
122
157
  - **Doctests:** Add examples for expected behavior
158
+ {% elif language == "typescript" -%}
159
+ - **Contracts FIRST:** Write Zod schemas before implementation
160
+ - **JSDoc Examples:** Add `@example` for expected behavior
161
+ {% endif -%}
123
162
  - **Design:** Decompose complex tasks into sub-functions
124
163
 
164
+ {% if language == "python" -%}
125
165
  ```python
126
166
  # SPECIFY before BUILD:
127
167
  @pre(lambda x: x > 0)
@@ -133,6 +173,24 @@ def calculate(x: int) -> int:
133
173
  """
134
174
  ... # Implementation comes in BUILD
135
175
  ```
176
+ {% elif language == "typescript" -%}
177
+ ```typescript
178
+ // SPECIFY before BUILD:
179
+ import { z } from 'zod';
180
+
181
+ const CalculateInput = z.number().positive();
182
+ const CalculateOutput = z.number().nonnegative();
183
+
184
+ /**
185
+ * @example calculate(10) // => 100
186
+ */
187
+ function calculate(x: number): number {
188
+ const validated = CalculateInput.parse(x);
189
+ // Implementation comes in BUILD
190
+ return CalculateOutput.parse(result);
191
+ }
192
+ ```
193
+ {% endif -%}
136
194
 
137
195
  ### 3. BUILD
138
196
 
@@ -1,226 +1,33 @@
1
- <!--invar:critical-->
2
- ## Critical Rules
3
-
4
- | Always | Remember |
5
- |--------|----------|
6
- {% if syntax == "mcp" -%}
7
- | **Verify** | `invar_guard` NOT pytest, NOT crosshair |
8
- {% else -%}
9
- | **Verify** | `invar guard` — NOT pytest, NOT crosshair |
10
- {% endif -%}
11
- | **Core** | `@pre/@post` + doctests, NO I/O imports |
12
- | **Shell** | Returns `Result[T, E]` from `returns` library |
13
- | **Flow** | USBV: Understand → Specify → Build → Validate |
14
-
15
- ### Contract Rules (CRITICAL)
16
-
17
- ```python
18
- # ❌ WRONG: Lambda must include ALL parameters
19
- @pre(lambda x: x >= 0)
20
- def calc(x: int, y: int = 0): ...
21
-
22
- # ✅ CORRECT: Include defaults too
23
- @pre(lambda x, y=0: x >= 0)
24
- def calc(x: int, y: int = 0): ...
25
-
26
- # ❌ WRONG: @post cannot access parameters
27
- @post(lambda result: result > x) # 'x' not available!
28
-
29
- # ✅ CORRECT: @post only sees 'result'
30
- @post(lambda result: result >= 0)
31
- ```
32
-
33
- <!--/invar:critical-->
1
+ {# CLAUDE.md Composition Template
2
+ Composes universal workflow + language-specific rules
3
+ Variables: language (python|typescript), syntax (mcp|cli), version
4
+ #}
5
+ {% if language == "python" %}
6
+ {% include "claude-md/python/critical-rules.md" %}
7
+ {% elif language == "typescript" %}
8
+ {% include "claude-md/typescript/critical-rules.md" %}
9
+ {% endif %}
34
10
 
35
11
  <!--invar:managed version="{{ version }}"-->
36
12
  # Project Development Guide
37
13
 
38
14
  > **Protocol:** Follow [INVAR.md](./INVAR.md) — includes Check-In, USBV workflow, and Task Completion requirements.
39
15
 
40
- ## Check-In
41
-
42
- > See [INVAR.md#check-in](./INVAR.md#check-in-required) for full protocol.
43
-
44
- **Your first message MUST display:** `✓ Check-In: [project] | [branch] | [clean/dirty]`
45
-
46
- **Actions:** Read `.invar/context.md`, then show status. Do NOT run guard at Check-In.
16
+ {% include "claude-md/universal/check-in.md" %}
47
17
 
48
18
  ---
49
19
 
50
- ## Final
51
-
52
- Your last message for an implementation task MUST display:
53
-
54
- ```
55
- ✓ Final: guard PASS | 0 errors, 2 warnings
56
- ```
57
-
58
- {% if syntax == "mcp" -%}
59
- Execute `invar_guard()` and show this one-line summary.
60
- {% else -%}
61
- Execute `invar guard` and show this one-line summary.
20
+ {% if language == "python" %}
21
+ {% include "claude-md/python/quick-reference.md" %}
22
+ {% elif language == "typescript" %}
23
+ {% include "claude-md/typescript/quick-reference.md" %}
62
24
  {% endif %}
63
25
 
64
- This is your sign-out. Completes the Check-In/Final pair.
26
+ {% include "claude-md/universal/workflow.md" %}
65
27
 
66
28
  ---
67
29
 
68
- ## Project Structure
69
-
70
- ```
71
- src/{project}/
72
- ├── core/ # Pure logic (@pre/@post, doctests, no I/O)
73
- └── shell/ # I/O operations (Result[T, E] return type)
74
- ```
75
-
76
- **Key insight:** Core receives data (strings), Shell handles I/O (paths, files).
77
-
78
- ## Quick Reference
79
-
80
- | Zone | Requirements |
81
- |------|-------------|
82
- | Core | `@pre`/`@post` + doctests, pure (no I/O) |
83
- | Shell | Returns `Result[T, E]` from `returns` library |
84
-
85
- ### Core vs Shell (Edge Cases)
86
-
87
- - File/network/env vars → **Shell**
88
- - `datetime.now()`, `random` → **Inject param** OR Shell
89
- - Pure logic → **Core**
90
-
91
- > Full decision tree: [INVAR.md#core-shell](./INVAR.md#decision-tree-core-vs-shell)
92
-
93
- ## Documentation Structure
94
-
95
- | File | Owner | Edit? | Purpose |
96
- |------|-------|-------|---------|
97
- | INVAR.md | Invar | No | Protocol (`invar update` to sync) |
98
- | CLAUDE.md | User | Yes | Project customization (this file) |
99
- | .invar/context.md | User | Yes | Project state, lessons learned |
100
- | .invar/project-additions.md | User | Yes | Project rules → injected into CLAUDE.md |
101
- | .invar/examples/ | Invar | No | **Must read:** Core/Shell patterns, workflow |
102
-
103
- > **Before writing code:** Check Task Router in `.invar/context.md`
104
-
105
- ## Visible Workflow (DX-30)
106
-
107
- For complex tasks (3+ functions), show 3 checkpoints in TodoList:
108
-
109
- ```
110
- □ [UNDERSTAND] Task description, codebase context, constraints
111
- □ [SPECIFY] Contracts (@pre/@post) and design decomposition
112
- □ [VALIDATE] Guard results, Review Gate status, integration status
113
- ```
114
-
115
- **BUILD is internal work** — not shown in TodoList.
116
-
117
- **Show contracts before code.** See `.invar/examples/workflow.md` for full example.
118
-
119
- ## Phase Visibility (DX-51)
120
-
121
- Each USBV phase transition requires a visible header:
122
-
123
- ```
124
- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
125
- 📍 /develop → SPECIFY (2/4)
126
- ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
127
- ```
128
-
129
- **Three-layer visibility:**
130
- - **Skill** (`/develop`) — Routing announcement
131
- - **Phase** (`SPECIFY 2/4`) — Phase header (this section)
132
- - **Tasks** — TodoWrite items
133
-
134
- Phase headers are SEPARATE from TodoWrite. Phase = where you are; TodoWrite = what to do.
135
-
136
- ---
137
-
138
- ## Context Management (DX-54)
139
-
140
- Re-read `.invar/context.md` when:
141
- 1. Entering any workflow (/develop, /review, etc.)
142
- 2. Completing a TodoWrite task (before moving to next)
143
- 3. Conversation exceeds ~15-20 exchanges
144
- 4. Unsure about project rules or patterns
145
-
146
- **Refresh is transparent** — do not announce "I'm refreshing context."
147
- Only show routing announcements when entering workflows.
148
-
149
- ---
150
-
151
- ## Commands (User-Invokable)
152
-
153
- | Command | Purpose |
154
- |---------|---------|
155
- | `/audit` | Read-only code review (reports issues, no fixes) |
156
- | `/guard` | Run Invar verification (reports results) |
157
-
158
- ## Skills (Agent-Invoked)
159
-
160
- | Skill | Triggers | Purpose |
161
- |-------|----------|---------|
162
- | `/investigate` | "why", "explain", vague tasks | Research mode, no code changes |
163
- | `/propose` | "should we", "compare" | Decision facilitation |
164
- | `/develop` | "add", "fix", "implement" | USBV implementation workflow |
165
- | `/review` | After /develop, `review_suggested` | Adversarial review with fix loop |
166
-
167
- **Note:** Skills are invoked by agent based on context. Use `/audit` for user-initiated review.
168
-
169
- Guard triggers `review_suggested` for: security-sensitive files, escape hatches >= 3, contract coverage < 50%.
170
-
171
- ---
172
-
173
- ## Workflow Routing (MANDATORY)
174
-
175
- When user message contains these triggers, you MUST use the **Skill tool** to invoke the skill:
176
-
177
- | Trigger Words | Skill Tool Call | Notes |
178
- |---------------|-----------------|-------|
179
- | "review", "review and fix" | `Skill(skill="review")` | Adversarial review with fix loop |
180
- | "implement", "add", "fix", "update" | `Skill(skill="develop")` | Unless in review context |
181
- | "why", "explain", "investigate" | `Skill(skill="investigate")` | Research mode, no code changes |
182
- | "compare", "should we", "design" | `Skill(skill="propose")` | Decision facilitation |
183
-
184
- **⚠️ CRITICAL: You must call the Skill tool, not just follow the workflow mentally.**
185
-
186
- The Skill tool reads `.claude/skills/<skill>/SKILL.md` which contains:
187
- - Detailed phase instructions (USBV breakdown)
188
- - Error handling rules
189
- - Timeout policies
190
- - Incremental development patterns (DX-63)
191
-
192
- **Violation check (before writing ANY code):**
193
- - "Did I call `Skill(skill="...")`?"
194
- - "Am I following the SKILL.md instructions?"
195
-
196
- ---
197
-
198
- ## Routing Control (DX-42)
199
-
200
- Agent announces routing decision before entering any workflow:
201
-
202
- ```
203
- 📍 Routing: /[skill] — [trigger or reason]
204
- Task: [summary]
205
- ```
206
-
207
- **User can redirect with natural language:**
208
- - "wait" / "stop" — pause and ask for direction
209
- - "just do it" — proceed with /develop
210
- - "let's discuss" — switch to /propose
211
- - "explain first" — switch to /investigate
212
-
213
- **Simple task optimization:** For simple tasks (single file, clear target, <50 lines), agent may offer:
214
-
215
- ```
216
- 📊 Simple task. Auto-orchestrate? [Y/N]
217
- ```
218
-
219
- - Y → Full cycle without intermediate confirmations
220
- - N → Normal step-by-step workflow
221
-
222
- **Auto-review (DX-41):** When Guard outputs `review_suggested`, agent automatically
223
- enters /review. Say "skip" to bypass.
30
+ {% include "claude-md/universal/skills.md" %}
224
31
  <!--/invar:managed-->
225
32
 
226
33
  <!--invar:project-->
@@ -13,8 +13,13 @@
13
13
  <!-- DX-54: Rules summary for long conversation resilience -->
14
14
 
15
15
  ### Core/Shell Separation
16
+ {% if language == "python" -%}
16
17
  - **Core** (`**/core/**`): @pre/@post + doctests, NO I/O imports
17
18
  - **Shell** (`**/shell/**`): Result[T, E] return type
19
+ {% elif language == "typescript" -%}
20
+ - **Core** (`**/core/**`): Contract comments (@pre/@post), no side effects
21
+ - **Shell** (`**/shell/**`): Result<T, E> return type
22
+ {% endif -%}
18
23
 
19
24
  ### USBV Workflow
20
25
  1. Understand → 2. Specify (contracts first) → 3. Build → 4. Validate
@@ -31,6 +36,7 @@
31
36
 
32
37
  <!-- Before writing code, check this table -->
33
38
 
39
+ {% if language == "python" %}
34
40
  | If you are about to... | STOP and read first |
35
41
  |------------------------|---------------------|
36
42
  | Write code in `core/` | `.invar/examples/contracts.py` |
@@ -38,6 +44,15 @@
38
44
  | Add `@pre`/`@post` contracts | `.invar/examples/contracts.py` |
39
45
  | Use functional patterns | `.invar/examples/functional.py` |
40
46
  | Implement a feature | `.invar/examples/workflow.md` |
47
+ {% elif language == "typescript" %}
48
+ | If you are about to... | STOP and read first |
49
+ |------------------------|---------------------|
50
+ | Write code in `core/` | `.invar/examples/contracts.ts` |
51
+ | Write code in `shell/` | `.invar/examples/core_shell.ts` |
52
+ | Add contract comments | `.invar/examples/contracts.ts` |
53
+ | Use functional patterns | `.invar/examples/functional.ts` |
54
+ | Implement a feature | `.invar/examples/workflow.md` |
55
+ {% endif %}
41
56
 
42
57
  **Rule:** Match found above? Read the file BEFORE writing code.
43
58
 
@@ -53,7 +68,11 @@
53
68
 
54
69
  **Quick rule check:**
55
70
  - Am I in Core or Shell?
71
+ {% if language == "python" -%}
56
72
  - Do I have @pre/@post contracts?
73
+ {% elif language == "typescript" -%}
74
+ - Do I have contract comments (@pre/@post)?
75
+ {% endif -%}
57
76
  - Am I following USBV workflow?
58
77
  - Did I run guard before claiming "done"?
59
78
 
@@ -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
+ | [functional.py](functional.py) | Functional patterns (NewType, Validation, NonEmpty, Literal) |
11
12
  | [workflow.md](workflow.md) | Visible USBV workflow example |
12
13
 
13
14
  ## Usage
@@ -16,6 +17,7 @@ Read these when you need:
16
17
  - Contract pattern reference
17
18
  - Core vs Shell decision guidance
18
19
  - Doctest formatting examples
20
+ - Functional pattern suggestions
19
21
  - USBV workflow example
20
22
 
21
23
  ---
@@ -1,3 +1,3 @@
1
1
  # Skip pytest collection for example files
2
2
  # These are reference examples, not tests.
3
- collect_ignore = ["contracts.py", "core_shell.py", "workflow.md"]
3
+ collect_ignore = ["contracts.py", "core_shell.py", "functional.py", "workflow.md"]
@@ -1,13 +1,14 @@
1
+ # ruff: noqa: ERA001
1
2
  """
2
3
  Invar Contract Examples
3
4
 
4
5
  Reference patterns for @pre/@post contracts and doctests.
5
6
  Managed by Invar - do not edit directly.
6
7
  """
8
+ # @invar:allow partial_contract: Educational file showing multiple @pre pattern
7
9
 
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
10
+ # invar_runtime supports both lambda and Contract objects
11
+ from invar_runtime import post, pre
11
12
 
12
13
  # =============================================================================
13
14
  # GOOD: Complete Contract
@@ -80,7 +81,7 @@ def normalize_keys(data: dict[str, int]) -> dict[str, int]:
80
81
  # DON'T: Empty contract tells nothing
81
82
  # @pre(lambda: True)
82
83
  # @post(lambda result: True)
83
- # def process(x): ... # noqa: ERA001
84
+ # def process(x): ...
84
85
 
85
86
  # DON'T: Missing edge cases in doctests
86
87
  # def divide(a, b):
@@ -111,3 +112,79 @@ def range_size(start: int, end: int) -> int:
111
112
  1
112
113
  """
113
114
  return end - start
115
+
116
+
117
+ # =============================================================================
118
+ # CRITICAL: Default Parameters in Contracts
119
+ # =============================================================================
120
+ # Lambda signatures MUST include ALL parameters, including defaults!
121
+ # This is a common mistake that causes silent contract failures.
122
+
123
+
124
+ # DON'T: Missing default parameter in lambda
125
+ # @pre(lambda x: x >= 0) # BAD: 'y' is missing!
126
+ # def calc_bad(x: int, y: int = 0) -> int:
127
+ # return x + y
128
+
129
+
130
+ # DO: Include all parameters with their defaults
131
+ @pre(lambda x, y=0: x >= 0 and y >= 0)
132
+ @post(lambda result: result >= 0)
133
+ def calculate_with_default(x: int, y: int = 0) -> int:
134
+ """
135
+ Calculate sum with optional y.
136
+
137
+ The lambda MUST include y=0 to match the function signature.
138
+
139
+ >>> calculate_with_default(5)
140
+ 5
141
+ >>> calculate_with_default(5, 3)
142
+ 8
143
+ >>> calculate_with_default(0, 0) # Edge: both zero
144
+ 0
145
+ """
146
+ return x + y
147
+
148
+
149
+ # =============================================================================
150
+ # CRITICAL: @post Cannot Access Parameters
151
+ # =============================================================================
152
+ # @post only receives the return value, not the original parameters!
153
+
154
+
155
+ # DON'T: Reference parameters in @post
156
+ # @post(lambda result: result > x) # BAD: 'x' is not available!
157
+ # def double_bad(x: int) -> int:
158
+ # return x * 2
159
+
160
+
161
+ # DO: @post only validates the result itself
162
+ @pre(lambda x: x >= 0)
163
+ @post(lambda result: result >= 0) # GOOD: only uses 'result'
164
+ def double_positive(x: int) -> int:
165
+ """
166
+ Double a positive number.
167
+
168
+ @post can only validate result properties, not relationships to inputs.
169
+
170
+ >>> double_positive(5)
171
+ 10
172
+ >>> double_positive(0) # Edge: zero
173
+ 0
174
+ """
175
+ return x * 2
176
+
177
+
178
+ # =============================================================================
179
+ # Decorator Order with @pre/@post
180
+ # =============================================================================
181
+ # When combining with other decorators, @pre/@post should be closest to function.
182
+
183
+
184
+ # DO: @pre/@post closest to function
185
+ # @other_decorator
186
+ # @pre(lambda x: x > 0)
187
+ # @post(lambda result: result > 0)
188
+ # def my_func(x: int) -> int: ...
189
+
190
+ # This ensures contracts run BEFORE other decorators modify behavior.