invar-tools 1.11.0__py3-none-any.whl → 1.12.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.
@@ -0,0 +1,238 @@
1
+ """TypeScript Compiler API wrapper (single-shot subprocess).
2
+
3
+ DX-78: Provides Python interface to ts-query.js for TypeScript analysis.
4
+
5
+ Architecture:
6
+ - Single-shot subprocess: starts, runs query, exits
7
+ - No persistent process, no orphan risk
8
+ - Falls back to regex parser if Node.js unavailable
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ import json
14
+ import subprocess
15
+ from dataclasses import dataclass
16
+ from pathlib import Path
17
+ from typing import Any
18
+
19
+ from returns.result import Failure, Result, Success
20
+
21
+
22
+ @dataclass
23
+ class TSSymbolInfo:
24
+ """TypeScript symbol information from Compiler API."""
25
+
26
+ name: str
27
+ kind: str
28
+ signature: str
29
+ line: int
30
+ file: str = ""
31
+ contracts: dict[str, list[str]] | None = None
32
+ members: list[dict[str, Any]] | None = None
33
+
34
+
35
+ @dataclass
36
+ class TSReference:
37
+ """A reference to a TypeScript symbol."""
38
+
39
+ file: str
40
+ line: int
41
+ column: int
42
+ context: str
43
+ is_definition: bool = False
44
+
45
+
46
+ def _find_ts_query_js() -> Path:
47
+ """Find the ts-query.js script bundled with invar-tools."""
48
+ # Look relative to this file's location
49
+ this_dir = Path(__file__).parent.parent
50
+ ts_query_path = this_dir / "node_tools" / "ts-query.js"
51
+
52
+ if ts_query_path.exists():
53
+ return ts_query_path
54
+
55
+ # Fallback: check if installed globally or in node_modules
56
+ raise FileNotFoundError("ts-query.js not found")
57
+
58
+
59
+ # @shell_complexity: Project root discovery with parent traversal
60
+ def _find_tsconfig_root(file_path: Path) -> Path:
61
+ """Find the project root containing tsconfig.json."""
62
+ current = file_path.parent if file_path.is_file() else file_path
63
+
64
+ while current != current.parent:
65
+ if (current / "tsconfig.json").exists():
66
+ return current
67
+ current = current.parent
68
+
69
+ # Fallback to file's directory
70
+ return file_path.parent if file_path.is_file() else file_path
71
+
72
+
73
+ # @shell_complexity: Subprocess orchestration with error handling and JSON parsing
74
+ def query_typescript(
75
+ project_root: Path,
76
+ command: str,
77
+ **params: Any,
78
+ ) -> Result[dict[str, Any], str]:
79
+ """Run ts-query.js and return parsed result.
80
+
81
+ Single-shot subprocess: starts, runs query, exits.
82
+ No persistent process, no orphan risk.
83
+
84
+ Args:
85
+ project_root: Project root containing tsconfig.json
86
+ command: Query command (sig, map, refs)
87
+ **params: Command-specific parameters
88
+
89
+ Returns:
90
+ Parsed JSON result or error message
91
+ """
92
+ try:
93
+ ts_query_path = _find_ts_query_js()
94
+ except FileNotFoundError:
95
+ return Failure("ts-query.js not found. Install Node.js to use TypeScript tools.")
96
+
97
+ query = {"command": command, **params}
98
+
99
+ try:
100
+ result = subprocess.run(
101
+ ["node", str(ts_query_path), json.dumps(query)],
102
+ cwd=str(project_root),
103
+ capture_output=True,
104
+ text=True,
105
+ timeout=30, # Safety timeout
106
+ )
107
+
108
+ if result.returncode != 0:
109
+ error_msg = result.stderr.strip() if result.stderr else "Unknown error"
110
+ return Failure(f"ts-query failed: {error_msg}")
111
+
112
+ output = json.loads(result.stdout)
113
+
114
+ # Check for error in output
115
+ if "error" in output:
116
+ return Failure(output["error"])
117
+
118
+ return Success(output)
119
+
120
+ except subprocess.TimeoutExpired:
121
+ return Failure("TypeScript query timed out (30s)")
122
+ except FileNotFoundError:
123
+ return Failure(
124
+ "Node.js not found.\n\n"
125
+ "To use TypeScript tools, install Node.js:\n"
126
+ "- macOS: brew install node\n"
127
+ "- Ubuntu: apt install nodejs\n"
128
+ "- Windows: https://nodejs.org/"
129
+ )
130
+ except json.JSONDecodeError as e:
131
+ return Failure(f"Invalid JSON from ts-query: {e}")
132
+ except Exception as e:
133
+ return Failure(f"TypeScript query error: {e}")
134
+
135
+
136
+ def run_sig_typescript(file_path: Path) -> Result[list[TSSymbolInfo], str]:
137
+ """Get signatures for TypeScript file using Compiler API.
138
+
139
+ Args:
140
+ file_path: Path to TypeScript file
141
+
142
+ Returns:
143
+ List of symbol information or error message
144
+ """
145
+ project_root = _find_tsconfig_root(file_path)
146
+ result = query_typescript(project_root, "sig", file=str(file_path))
147
+
148
+ if isinstance(result, Failure):
149
+ return result
150
+
151
+ data = result.unwrap()
152
+ symbols = []
153
+
154
+ for sym in data.get("symbols", []):
155
+ symbols.append(
156
+ TSSymbolInfo(
157
+ name=sym.get("name", ""),
158
+ kind=sym.get("kind", ""),
159
+ signature=sym.get("signature", ""),
160
+ line=sym.get("line", 0),
161
+ file=str(file_path),
162
+ contracts=sym.get("contracts"),
163
+ members=sym.get("members"),
164
+ )
165
+ )
166
+
167
+ return Success(symbols)
168
+
169
+
170
+ def run_map_typescript(path: Path, top_n: int) -> Result[dict[str, Any], str]:
171
+ """Get symbol map with reference counts for TypeScript project.
172
+
173
+ Args:
174
+ path: Project path to scan
175
+ top_n: Maximum number of symbols to return
176
+
177
+ Returns:
178
+ Symbol map data or error message
179
+ """
180
+ return query_typescript(path, "map", path=str(path), top=top_n)
181
+
182
+
183
+ def run_refs_typescript(
184
+ file_path: Path, line: int, column: int
185
+ ) -> Result[list[TSReference], str]:
186
+ """Find all references to symbol at position.
187
+
188
+ Args:
189
+ file_path: File containing the symbol
190
+ line: 1-based line number
191
+ column: 0-based column number
192
+
193
+ Returns:
194
+ List of references or error message
195
+ """
196
+ project_root = _find_tsconfig_root(file_path)
197
+ result = query_typescript(
198
+ project_root,
199
+ "refs",
200
+ file=str(file_path),
201
+ line=line,
202
+ column=column,
203
+ )
204
+
205
+ if isinstance(result, Failure):
206
+ return result
207
+
208
+ data = result.unwrap()
209
+ references = []
210
+
211
+ for ref in data.get("references", []):
212
+ references.append(
213
+ TSReference(
214
+ file=ref.get("file", ""),
215
+ line=ref.get("line", 0),
216
+ column=ref.get("column", 0),
217
+ context=ref.get("context", ""),
218
+ is_definition=ref.get("isDefinition", False),
219
+ )
220
+ )
221
+
222
+ return Success(references)
223
+
224
+
225
+ def is_typescript_available() -> bool:
226
+ """Check if TypeScript Compiler API tools are available."""
227
+ try:
228
+ _find_ts_query_js()
229
+ # Also check if Node.js is available
230
+ result = subprocess.run(
231
+ ["node", "--version"],
232
+ capture_output=True,
233
+ text=True,
234
+ timeout=5,
235
+ )
236
+ return result.returncode == 0
237
+ except (FileNotFoundError, subprocess.TimeoutExpired):
238
+ return False
@@ -0,0 +1,193 @@
1
+ # TypeScript Patterns for Agents
2
+
3
+ Reference patterns for AI agents working with TypeScript under Invar Protocol.
4
+
5
+ ## Tool × Feature Matrix
6
+
7
+ | Feature | TypeScript Pattern | Tool Command |
8
+ |---------|-------------------|--------------|
9
+ | Signatures | `function name(params): Return` | `invar sig file.ts` |
10
+ | Contracts | `@pre`, `@post` JSDoc + Zod | `invar sig file.ts` |
11
+ | References | Cross-file symbol usage | `invar refs file.ts::Symbol` |
12
+ | Verification | tsc + eslint + vitest | `invar guard` |
13
+ | Document nav | Markdown structure | `invar doc toc file.md` |
14
+
15
+ ---
16
+
17
+ ## Pattern 1: Preconditions with Zod
18
+
19
+ ```typescript
20
+ import { z } from 'zod';
21
+
22
+ // Schema IS the precondition
23
+ const UserInputSchema = z.object({
24
+ email: z.string().email(),
25
+ age: z.number().int().positive().max(150),
26
+ });
27
+
28
+ type UserInput = z.infer<typeof UserInputSchema>;
29
+
30
+ /**
31
+ * Create a user with validated input.
32
+ * @pre UserInputSchema.parse(input) succeeds
33
+ * @post result.id is set
34
+ */
35
+ function createUser(input: UserInput): User {
36
+ // Zod already validated - safe to use
37
+ return { id: generateId(), ...input };
38
+ }
39
+ ```
40
+
41
+ **Agent workflow:**
42
+ 1. Define Zod schema FIRST (the @pre)
43
+ 2. Derive TypeScript type from schema
44
+ 3. Implement function body
45
+ 4. Zod validates at runtime
46
+
47
+ ---
48
+
49
+ ## Pattern 2: Postconditions
50
+
51
+ ```typescript
52
+ /**
53
+ * Calculate discount price.
54
+ * @pre price > 0 && discount >= 0 && discount <= 1
55
+ * @post result >= 0 && result <= price
56
+ */
57
+ function applyDiscount(price: number, discount: number): number {
58
+ const result = price * (1 - discount);
59
+
60
+ // Postcondition check (development only)
61
+ console.assert(result >= 0 && result <= price,
62
+ `Postcondition failed: ${result}`);
63
+
64
+ return result;
65
+ }
66
+ ```
67
+
68
+ **Note:** Unlike Python's `@post` decorator, TypeScript postconditions
69
+ are documented in JSDoc and checked manually or via assertion.
70
+
71
+ ---
72
+
73
+ ## Pattern 3: Core/Shell Separation
74
+
75
+ ```typescript
76
+ // ─── Core (Pure) ───
77
+ // No I/O, no side effects, only data transformations
78
+
79
+ function validateEmail(email: string): boolean {
80
+ return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
81
+ }
82
+
83
+ function calculateTotal(items: CartItem[]): number {
84
+ return items.reduce((sum, item) => sum + item.price * item.qty, 0);
85
+ }
86
+
87
+ // ─── Shell (I/O) ───
88
+ // All external interactions, returns Result<T, E>
89
+
90
+ import { Result, ok, err } from 'neverthrow';
91
+
92
+ async function fetchUser(id: string): Promise<Result<User, ApiError>> {
93
+ try {
94
+ const response = await fetch(`/api/users/${id}`);
95
+ if (!response.ok) return err({ code: response.status });
96
+ return ok(await response.json());
97
+ } catch (e) {
98
+ return err({ code: 500, message: String(e) });
99
+ }
100
+ }
101
+ ```
102
+
103
+ **Agent checklist:**
104
+ - [ ] Core functions: No imports from `fs`, `http`, `fetch`, etc.
105
+ - [ ] Shell functions: Return `Result<T, E>` for fallible operations
106
+ - [ ] Dependency injection: Pass data to Core, not paths
107
+
108
+ ---
109
+
110
+ ## Pattern 4: Exhaustive Switch
111
+
112
+ ```typescript
113
+ type Status = 'pending' | 'approved' | 'rejected';
114
+
115
+ function getStatusMessage(status: Status): string {
116
+ switch (status) {
117
+ case 'pending': return 'Waiting for review';
118
+ case 'approved': return 'Request approved';
119
+ case 'rejected': return 'Request denied';
120
+ default:
121
+ // TypeScript ensures this is never reached
122
+ const _exhaustive: never = status;
123
+ throw new Error(`Unknown status: ${_exhaustive}`);
124
+ }
125
+ }
126
+ ```
127
+
128
+ **Why:** Adding a new status forces handling in all switches.
129
+
130
+ ---
131
+
132
+ ## Pattern 5: Branded Types
133
+
134
+ ```typescript
135
+ // Nominal typing for semantic safety
136
+ type UserId = string & { readonly __brand: 'UserId' };
137
+ type OrderId = string & { readonly __brand: 'OrderId' };
138
+
139
+ function createUserId(id: string): UserId {
140
+ return id as UserId;
141
+ }
142
+
143
+ // Compiler prevents mixing IDs
144
+ function getUser(id: UserId): User { ... }
145
+ function getOrder(id: OrderId): Order { ... }
146
+
147
+ getUser(orderId); // ❌ Type error: OrderId is not UserId
148
+ ```
149
+
150
+ ---
151
+
152
+ ## Tool Usage Examples
153
+
154
+ ### View signatures
155
+
156
+ ```bash
157
+ $ invar sig src/auth.ts
158
+ src/auth.ts
159
+ function validateToken(token: string): boolean
160
+ @pre token.length > 0
161
+ @post result indicates valid JWT
162
+
163
+ class AuthService
164
+ method login(email: string, password: string): Promise<Result<Token, AuthError>>
165
+ method logout(): Promise<void>
166
+ ```
167
+
168
+ ### Find references
169
+
170
+ ```bash
171
+ $ invar refs src/auth.ts::validateToken
172
+ src/auth.ts:15 — Definition
173
+ src/routes/api.ts:42 — if (validateToken(req.headers.auth)) {
174
+ src/middleware/auth.ts:18 — const isValid = validateToken(token);
175
+ tests/auth.test.ts:8 — expect(validateToken('invalid')).toBe(false);
176
+ ```
177
+
178
+ ### Verify code
179
+
180
+ ```bash
181
+ $ invar guard
182
+ TypeScript Guard Report
183
+ ========================================
184
+ [PASS] tsc --noEmit (no type errors)
185
+ [PASS] eslint (0 errors, 2 warnings)
186
+ [PASS] vitest (24 tests passed)
187
+ ----------------------------------------
188
+ Guard passed.
189
+ ```
190
+
191
+ ---
192
+
193
+ *Managed by Invar - regenerated on `invar update`*
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: invar-tools
3
- Version: 1.11.0
3
+ Version: 1.12.0
4
4
  Summary: AI-native software engineering tools with design-by-contract verification
5
5
  Project-URL: Homepage, https://github.com/tefx/invar
6
6
  Project-URL: Documentation, https://github.com/tefx/invar#readme
@@ -24,6 +24,7 @@ Requires-Python: >=3.11
24
24
  Requires-Dist: crosshair-tool>=0.0.60
25
25
  Requires-Dist: hypothesis>=6.0
26
26
  Requires-Dist: invar-runtime>=1.0
27
+ Requires-Dist: jedi>=0.19
27
28
  Requires-Dist: jinja2>=3.0
28
29
  Requires-Dist: markdown-it-py>=3.0
29
30
  Requires-Dist: mcp>=1.0
@@ -146,7 +147,19 @@ Guard passed.
146
147
 
147
148
  ## 🚀 Quick Start
148
149
 
149
- > **Language Support:** Python (full), TypeScript (verification via Zod contracts).
150
+ ### Tool × Language Support
151
+
152
+ | Tool | Python | TypeScript | Notes |
153
+ |------|--------|------------|-------|
154
+ | `invar guard` | ✅ Full | ⚠️ Partial | TS: tsc + eslint + vitest |
155
+ | `invar sig` | ✅ Full | ✅ Full | TS: TS Compiler API |
156
+ | `invar map` | ✅ Full | ✅ Full | TS: With reference counts |
157
+ | `invar refs` | ✅ Full | ✅ Full | Cross-file reference finding |
158
+ | `invar doc *` | ✅ Full | ✅ Full | Language-agnostic |
159
+
160
+ **TypeScript Notes:**
161
+ - Requires Node.js + TypeScript (most TS projects have these)
162
+ - Falls back to regex parser if Node.js unavailable
150
163
 
151
164
  ### 📦 Two Packages, Different Purposes
152
165
 
@@ -303,14 +316,17 @@ function average(items: number[]): number {
303
316
 
304
317
  ### ✅ Solution 2: Multi-Layer Verification
305
318
 
306
- Guard provides fast feedback. Agent sees errors, fixes immediately:
319
+ Guard provides fast feedback **on top of standard type checking**. Agent sees errors, fixes immediately:
307
320
 
308
321
  | Layer | Tool | Speed | What It Catches |
309
322
  |-------|------|-------|-----------------|
323
+ | **Type Check*** | mypy (Python) / tsc (TypeScript) | ~1s | Type errors, missing annotations |
310
324
  | **Static** | Guard rules | ~0.5s | Architecture violations, missing contracts |
311
- | **Doctest** | pytest | ~2s | Example correctness |
312
- | **Property** | Hypothesis | ~10s | Edge cases via random inputs |
313
- | **Symbolic** | CrossHair | ~30s | Mathematical proof of contracts |
325
+ | **Doctest** | pytest / vitest | ~2s | Example correctness |
326
+ | **Property** | Hypothesis / fast-check | ~10s | Edge cases via random inputs |
327
+ | **Symbolic** | CrossHair / (TS: N/A) | ~30s | Mathematical proof of contracts |
328
+
329
+ <sup>* Requires separate installation: `pip install mypy` or configure TypeScript in your project</sup>
314
330
 
315
331
  ```
316
332
  ┌──────────┐ ┌───────────┐ ┌───────────┐ ┌────────────┐
@@ -525,7 +541,7 @@ Cursor users get full verification via MCP:
525
541
  |----------------|---------|----------|
526
542
  | `INVAR.md` | Protocol for AI agents | Required |
527
543
  | `.invar/` | Config, context, examples | Required |
528
- | `.pre-commit-config.yaml` | Verification before commit | Optional |
544
+ | `.pre-commit-config.yaml` | Verification before commit (Ruff, mypy*, Guard) | Optional |
529
545
  | `src/core/`, `src/shell/` | Recommended structure | Optional |
530
546
  | `CLAUDE.md` | Agent instructions | Claude Code |
531
547
  | `.claude/skills/` | Workflow + extension skills | Claude Code |
@@ -534,6 +550,8 @@ Cursor users get full verification via MCP:
534
550
  | `.mcp.json` | MCP server config | Claude Code |
535
551
  | `AGENT.md` | Universal agent instructions | Other agents |
536
552
 
553
+ <sup>* mypy hook included in `.pre-commit-config.yaml` but requires: `pip install mypy`</sup>
554
+
537
555
  **Note:** If `pyproject.toml` exists, Guard configuration goes there as `[tool.invar.guard]` instead of `.invar/config.toml`.
538
556
 
539
557
  **Recommended structure:**
@@ -49,10 +49,11 @@ invar/core/patterns/registry.py,sha256=2rz0wWDRarMkuHN-qM_ZrT3qeGFDSKMABvRvPNZxQ
49
49
  invar/core/patterns/types.py,sha256=ULAlWuAdmO6CFcEDjTrWBfzNTBsnomAl2d25tR11ihU,5506
50
50
  invar/mcp/__init__.py,sha256=n3S7QwMjSMqOMT8cI2jf9E0yZPjKmBOJyIYhq4WZ8TQ,226
51
51
  invar/mcp/__main__.py,sha256=ZcIT2U6xUyGOWucl4jq422BDE3lRLjqyxb9pFylRBdk,219
52
- invar/mcp/handlers.py,sha256=usPgYvNLB3nE1G8gkA3LtKKNQ4k_eXQEr4GueA-8NSw,14939
53
- invar/mcp/server.py,sha256=nDEHhF-eDkyNOX-y-wsZDa6Ed2nvjk5HtIC9SIbi7z0,18491
52
+ invar/mcp/handlers.py,sha256=b0LRWKMpu6lnjPV7SozH0cxKYJufVWy3eJhiAu3of-M,15947
53
+ invar/mcp/server.py,sha256=WmVNs2_AcOMbmp3tEgWR57hjqqJkMx3nV3z9fcNuSAA,20109
54
54
  invar/node_tools/MANIFEST,sha256=UwtO2AsQ-0UwskG6ZkE2kXqz_hdp-gzRTyp32-X22Mc,131
55
55
  invar/node_tools/__init__.py,sha256=HzILh3jtP28Lm2jZwss1SY65ECxbtw2J2uFpXQA6Y94,1740
56
+ invar/node_tools/ts-query.js,sha256=fEc_f0JT_Mb18dEoA4_vJoazvd7Lqv_rsed4eHSAbCg,13303
56
57
  invar/node_tools/fc-runner/cli.js,sha256=72_gIhvnx2peKITdzdnFWI5fzGaNTS3BcEqyS628cI0,243277
57
58
  invar/node_tools/quick-check/cli.js,sha256=dwV3hdJleFQga2cKUn3PPfQDvvujhzKdjQcIvWsKgM0,66196
58
59
  invar/node_tools/ts-analyzer/cli.js,sha256=SvZ6HyjmobpP8NAZqXFiy8BwH_t5Hb17Ytar_18udaQ,4092887
@@ -71,19 +72,21 @@ invar/shell/mutation.py,sha256=Lfyk2b8j8-hxAq-iwAgQeOhr7Ci6c5tRF1TXe3CxQCs,8914
71
72
  invar/shell/pattern_integration.py,sha256=pRcjfq3NvMW_tvQCnaXZnD1k5AVEWK8CYOE2jN6VTro,7842
72
73
  invar/shell/pi_hooks.py,sha256=ulZc1sP8mTRJTBsjwFHQzUgg-h8ajRIMp7iF1Y4UUtw,6885
73
74
  invar/shell/property_tests.py,sha256=N9JreyH5PqR89oF5yLcX7ZAV-Koyg5BKo-J05-GUPsA,9109
75
+ invar/shell/py_refs.py,sha256=Vjz50lmt9prDBcBv4nkkODdiJ7_DKu5zO4UPZBjAfmM,4638
74
76
  invar/shell/skill_manager.py,sha256=Mr7Mh9rxPSKSAOTJCAM5ZHiG5nfUf6KQVCuD4LBNHSI,12440
75
77
  invar/shell/subprocess_env.py,sha256=9oXl3eMEbzLsFEgMHqobEw6oW_wV0qMEP7pklwm58Pw,11453
76
78
  invar/shell/template_engine.py,sha256=eNKMz7R8g9Xp3_1TGx-QH137jf52E0u3KaVcnotu1Tg,12056
77
79
  invar/shell/templates.py,sha256=31f5ieoGeWU0qqfLJUMWnz0yyLa1FBc_sOz6UGzToqk,13884
78
80
  invar/shell/testing.py,sha256=rTNBH0Okh2qtG9ohSXOz487baQ2gXrWT3s_WECW3HJs,11143
81
+ invar/shell/ts_compiler.py,sha256=nA8brnOhThj9J_J3vAEGjDsM4NjbWQ_eX8Yf4pHPOgk,6672
79
82
  invar/shell/commands/__init__.py,sha256=MEkKwVyjI9DmkvBpJcuumXo2Pg_FFkfEr-Rr3nrAt7A,284
80
83
  invar/shell/commands/doc.py,sha256=SOLDoCXXGxx_JU0PKXlAIGEF36PzconHmmAtL-rM6D4,13819
81
- invar/shell/commands/guard.py,sha256=-QYR2wc-KjD6VL9tb9Ih6gr5LFX-H7_H843TX5qR5wk,23686
84
+ invar/shell/commands/guard.py,sha256=p0kI63RUzC1OTh_YviviY6dz2bq_SoBksGOp2NyocQM,24512
82
85
  invar/shell/commands/hooks.py,sha256=W-SOnT4VQyUvXwipozkJwgEYfiOJGz7wksrbcdWegUg,2356
83
86
  invar/shell/commands/init.py,sha256=-FZTYTwJr_NRoluAM4YwcseNju56GSxtnKVkqsXREPg,20461
84
87
  invar/shell/commands/merge.py,sha256=nuvKo8m32-OL-SCQlS4SLKmOZxQ3qj-1nGCx1Pgzifw,8183
85
88
  invar/shell/commands/mutate.py,sha256=GwemiO6LlbGCBEQsBFnzZuKhF-wIMEl79GAMnKUWc8U,5765
86
- invar/shell/commands/perception.py,sha256=MDJvjLcrT7ZjhT4L1zjaMoQpjQaHe9qNWHdy-7yECrQ,8524
89
+ invar/shell/commands/perception.py,sha256=HewSv6Kv8Gw2UQqkGY2rP5YKlnwyC3LBrQ2hFVXXw30,19304
87
90
  invar/shell/commands/skill.py,sha256=oKVyaxQ_LK28FpJhRpBDpXcpRdUBK3n6rC0qD77ax1M,5803
88
91
  invar/shell/commands/sync_self.py,sha256=nmqBry7V2_enKwy2zzHg8UoedZNicLe3yKDhjmBeZ68,3880
89
92
  invar/shell/commands/template_sync.py,sha256=aNWyFPMFT7pSwHrvwGCqcKAwb4dp7S9tvZzy9H4gAnw,16094
@@ -124,6 +127,7 @@ invar/templates/examples/typescript/README.md,sha256=I6kVTJAk6wqb21eC09hyOZXRP74
124
127
  invar/templates/examples/typescript/contracts.ts,sha256=X6EeNUAurw9MHJlHPDos_JtnScMu2aDMSkveIaA4wHs,4597
125
128
  invar/templates/examples/typescript/core_shell.ts,sha256=VuPl0xmn_s6pA7ZJtq0zNjXzK_DRmq3LexwTS8MEqnQ,11267
126
129
  invar/templates/examples/typescript/functional.ts,sha256=bQHfl0EYDC_RziRQLJBgPNBGhWBBO7SVSVchqBJUetM,17347
130
+ invar/templates/examples/typescript/patterns.md,sha256=rlZ6IOC8iYUQzIXaW7fUf95OQbeWPWSjQXDDJNoU05E,4859
127
131
  invar/templates/examples/typescript/workflow.md,sha256=5byADjA3WgOgiDbkEtVRKKGvlhvu3EbFCzqEg9lEV7k,2764
128
132
  invar/templates/hooks/PostToolUse.sh.jinja,sha256=JHJGMdF3xp2qEqkPC9GaLp0NCa5gdRzqAmgRy4IldBg,3428
129
133
  invar/templates/hooks/PreToolUse.sh.jinja,sha256=tZb-FGFxOBtTprUfeChau7rZOMPII69_5HSF-i_WD4Q,3558
@@ -169,10 +173,10 @@ invar/templates/skills/extensions/security/patterns/typescript.yaml,sha256=qDEg-
169
173
  invar/templates/skills/investigate/SKILL.md.jinja,sha256=cp6TBEixBYh1rLeeHOR1yqEnFqv1NZYePORMnavLkQI,3231
170
174
  invar/templates/skills/propose/SKILL.md.jinja,sha256=6BuKiCqO1AEu3VtzMHy1QWGqr_xqG9eJlhbsKT4jev4,3463
171
175
  invar/templates/skills/review/SKILL.md.jinja,sha256=ET5mbdSe_eKgJbi2LbgFC-z1aviKcHOBw7J5Q28fr4U,14105
172
- invar_tools-1.11.0.dist-info/METADATA,sha256=ZqSNbqNPK1MeTHJ-dEOEqR1HCJfJeDrMIkalsjef59w,27504
173
- invar_tools-1.11.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
174
- invar_tools-1.11.0.dist-info/entry_points.txt,sha256=RwH_EhqgtFPsnO6RcrwrAb70Zyfb8Mh6uUtztWnUxGk,102
175
- invar_tools-1.11.0.dist-info/licenses/LICENSE,sha256=qeFksp4H4kfTgQxPCIu3OdagXyiZcgBlVfsQ6M5oFyk,10767
176
- invar_tools-1.11.0.dist-info/licenses/LICENSE-GPL,sha256=IvZfC6ZbP7CLjytoHVzvpDZpD-Z3R_qa1GdMdWlWQ6Q,35157
177
- invar_tools-1.11.0.dist-info/licenses/NOTICE,sha256=joEyMyFhFY8Vd8tTJ-a3SirI0m2Sd0WjzqYt3sdcglc,2561
178
- invar_tools-1.11.0.dist-info/RECORD,,
176
+ invar_tools-1.12.0.dist-info/METADATA,sha256=jpbC0FFokpDTexuAf5nodUMsRM46nU5-ZC0SmVVN5cQ,28409
177
+ invar_tools-1.12.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
178
+ invar_tools-1.12.0.dist-info/entry_points.txt,sha256=RwH_EhqgtFPsnO6RcrwrAb70Zyfb8Mh6uUtztWnUxGk,102
179
+ invar_tools-1.12.0.dist-info/licenses/LICENSE,sha256=qeFksp4H4kfTgQxPCIu3OdagXyiZcgBlVfsQ6M5oFyk,10767
180
+ invar_tools-1.12.0.dist-info/licenses/LICENSE-GPL,sha256=IvZfC6ZbP7CLjytoHVzvpDZpD-Z3R_qa1GdMdWlWQ6Q,35157
181
+ invar_tools-1.12.0.dist-info/licenses/NOTICE,sha256=joEyMyFhFY8Vd8tTJ-a3SirI0m2Sd0WjzqYt3sdcglc,2561
182
+ invar_tools-1.12.0.dist-info/RECORD,,