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,56 @@
1
+ ## Contract Syntax (Python)
2
+
3
+ ### Lambda Signature (Critical)
4
+
5
+ ```python
6
+ # WRONG: Lambda only takes first parameter
7
+ @pre(lambda x: x >= 0)
8
+ def calculate(x: int, y: int = 0): ...
9
+
10
+ # CORRECT: Lambda must include ALL parameters (even defaults)
11
+ @pre(lambda x, y=0: x >= 0)
12
+ def calculate(x: int, y: int = 0): ...
13
+ ```
14
+
15
+ Guard's `param_mismatch` rule catches this as ERROR.
16
+
17
+ ### Meaningful Contracts
18
+
19
+ ```python
20
+ # Redundant - type hints already check this
21
+ @pre(lambda x: isinstance(x, int))
22
+ def calc(x: int): ...
23
+
24
+ # Meaningful - checks business logic
25
+ @pre(lambda x: x > 0)
26
+ def calc(x: int): ...
27
+
28
+ # Meaningful - checks relationship between params
29
+ @pre(lambda start, end: start < end)
30
+ def process_range(start: int, end: int): ...
31
+ ```
32
+
33
+ ### @post Scope
34
+
35
+ ```python
36
+ # WRONG: @post cannot access function parameters
37
+ @post(lambda result: result > x) # 'x' not available!
38
+ def calc(x: int) -> int: ...
39
+
40
+ # CORRECT: @post can only use 'result'
41
+ @post(lambda result: result >= 0)
42
+ def calc(x: int) -> int: ...
43
+ ```
44
+
45
+ ### Doctest Examples
46
+
47
+ ```python
48
+ def calculate(x: int) -> int:
49
+ """
50
+ >>> calculate(5)
51
+ 10
52
+ >>> calculate(0) # Edge case
53
+ 0
54
+ """
55
+ return x * 2
56
+ ```
@@ -0,0 +1,44 @@
1
+ ## Markers (Python)
2
+
3
+ ### Entry Points
4
+
5
+ Entry points are framework callbacks (`@app.route`, `@app.command`) at Shell boundary.
6
+ - **Exempt** from `Result[T, E]` — must match framework signature
7
+ - **Keep thin** (max 15 lines) — delegate to Shell functions that return Result
8
+
9
+ Auto-detected by decorators. For custom callbacks:
10
+
11
+ ```python
12
+ # @shell:entry
13
+ def on_custom_event(data: dict) -> dict:
14
+ result = handle_event(data)
15
+ return result.unwrap_or({"error": "failed"})
16
+ ```
17
+
18
+ ### Shell Complexity
19
+
20
+ When shell function complexity is justified:
21
+
22
+ ```python
23
+ # @shell_complexity: Subprocess with error classification
24
+ def run_external_tool(...): ...
25
+
26
+ # @shell_orchestration: Multi-step pipeline coordination
27
+ def process_batch(...): ...
28
+ ```
29
+
30
+ ### Architecture Escape Hatch
31
+
32
+ When rule violation has valid architectural justification:
33
+
34
+ ```python
35
+ # @invar:allow shell_result: Framework callback signature fixed
36
+ def flask_handler(): ...
37
+ ```
38
+
39
+ **Valid rule names for @invar:allow:**
40
+ - `shell_result` — Shell function without Result return type
41
+ - `entry_point_too_thick` — Entry point exceeds 15 lines
42
+ - `forbidden_import` — I/O import in Core (rare, justify carefully)
43
+
44
+ Run `invar rules` for complete rule catalog with hints.
@@ -0,0 +1,24 @@
1
+ ## Commands (Python)
2
+
3
+ ```bash
4
+ invar guard # Full: static + doctests + CrossHair + Hypothesis
5
+ invar guard --static # Static only (quick debug, ~0.5s)
6
+ invar guard --changed # Modified files only
7
+ invar guard --coverage # Collect branch coverage
8
+ invar guard -c # Contract coverage only (DX-63)
9
+ invar sig <file> # Show contracts + signatures
10
+ invar map --top 10 # Most-referenced symbols
11
+ invar rules # List all rules with detection/hints (JSON)
12
+ ```
13
+
14
+ ## Configuration (Python)
15
+
16
+ ```toml
17
+ # pyproject.toml or invar.toml
18
+ [tool.invar.guard]
19
+ core_paths = ["src/myapp/core"] # Default: ["src/core", "core"]
20
+ shell_paths = ["src/myapp/shell"] # Default: ["src/shell", "shell"]
21
+ max_file_lines = 500 # Default: 500 (warning at 80%)
22
+ max_function_lines = 50 # Default: 50
23
+ # Doctest lines are excluded from size calculations
24
+ ```
@@ -0,0 +1,38 @@
1
+ ## Troubleshooting (Python)
2
+
3
+ ### Size Limits (Agent Quick Reference)
4
+
5
+ | Rule | Limit | Fix |
6
+ |------|-------|-----|
7
+ | `function_too_long` | **50 lines** | Extract helper: `_impl()` + main with docstring |
8
+ | `file_too_long` | **500 lines** | Split by responsibility |
9
+ | `entry_point_too_thick` | **15 lines** | Delegate to Shell functions |
10
+
11
+ *Doctest lines excluded from counts. Limits configurable in `pyproject.toml`.*
12
+
13
+ ### Common Errors
14
+
15
+ | Symptom | Cause | Fix |
16
+ |---------|-------|-----|
17
+ | `param_mismatch` error | Lambda missing params | Include ALL params (even defaults) |
18
+ | `shell_result` error | Shell func no Result | Add Result[T,E] or @invar:allow |
19
+ | `is_failure()` not found | Wrong Result check | Use `isinstance(result, Failure)` |
20
+
21
+ ### Result Type Usage
22
+
23
+ ```python
24
+ from returns.result import Result, Success, Failure
25
+
26
+ # Creating results
27
+ return Success(value)
28
+ return Failure(error)
29
+
30
+ # Checking results
31
+ if isinstance(result, Failure):
32
+ handle_error(result.failure())
33
+ else:
34
+ use_value(result.unwrap())
35
+
36
+ # Chaining
37
+ result.map(transform).bind(next_operation)
38
+ ```
@@ -0,0 +1,52 @@
1
+ ## Core Example (TypeScript)
2
+
3
+ ```typescript
4
+ import { z } from 'zod';
5
+
6
+ // Contracts as Zod schemas
7
+ const DiscountInput = z.object({
8
+ price: z.number().positive(),
9
+ discount: z.number().min(0).max(1),
10
+ });
11
+
12
+ const DiscountOutput = z.number().nonnegative();
13
+
14
+ /**
15
+ * @example discountedPrice({ price: 100, discount: 0.2 }) // => 80
16
+ * @example discountedPrice({ price: 100, discount: 0 }) // => 100 (edge: no discount)
17
+ */
18
+ export function discountedPrice(input: z.infer<typeof DiscountInput>): number {
19
+ const { price, discount } = DiscountInput.parse(input);
20
+ const result = price * (1 - discount);
21
+ return DiscountOutput.parse(result);
22
+ }
23
+ ```
24
+
25
+ **Self-test:** Can someone else write the exact same function from just Zod schemas + @example?
26
+
27
+ **Forbidden in Core:** `fs`, `path`, `http`, `fetch`, `process.env`, `Date.now()`
28
+
29
+ ## Shell Example (TypeScript)
30
+
31
+ ```typescript
32
+ import { Result, ok, err } from 'neverthrow';
33
+ import { readFileSync } from 'fs';
34
+
35
+ interface Config { [key: string]: unknown }
36
+
37
+ export function readConfig(path: string): Result<Config, string> {
38
+ try {
39
+ const content = readFileSync(path, 'utf-8');
40
+ return ok(JSON.parse(content));
41
+ } catch (e) {
42
+ if (e instanceof Error && 'code' in e && e.code === 'ENOENT') {
43
+ return err(`File not found: ${path}`);
44
+ }
45
+ return err(`Invalid JSON: ${e}`);
46
+ }
47
+ }
48
+ ```
49
+
50
+ **Pattern:** Shell reads file → passes content to Core → returns Result.
51
+
52
+ More examples: `.invar/examples/`
@@ -0,0 +1,73 @@
1
+ ## Contract Syntax (TypeScript)
2
+
3
+ ### Zod Schema Patterns
4
+
5
+ ```typescript
6
+ import { z } from 'zod';
7
+
8
+ // Input validation (precondition)
9
+ const CalcInput = z.object({
10
+ x: z.number().int().nonnegative(),
11
+ y: z.number().int().default(0),
12
+ });
13
+
14
+ // Output validation (postcondition)
15
+ const CalcOutput = z.number().int().nonnegative();
16
+
17
+ function calculate(input: z.infer<typeof CalcInput>): number {
18
+ const { x, y } = CalcInput.parse(input);
19
+ const result = x + y;
20
+ return CalcOutput.parse(result);
21
+ }
22
+ ```
23
+
24
+ ### Meaningful Contracts
25
+
26
+ ```typescript
27
+ // Redundant - TypeScript already checks this
28
+ const BadSchema = z.object({
29
+ x: z.number(), // Just type checking
30
+ });
31
+
32
+ // Meaningful - checks business logic
33
+ const GoodSchema = z.object({
34
+ x: z.number().positive(), // Domain constraint
35
+ });
36
+
37
+ // Meaningful - checks relationship
38
+ const RangeInput = z.object({
39
+ start: z.number(),
40
+ end: z.number(),
41
+ }).refine(data => data.start < data.end, {
42
+ message: "start must be less than end",
43
+ });
44
+ ```
45
+
46
+ ### Postcondition Scope
47
+
48
+ ```typescript
49
+ // Output schema can only validate the result
50
+ const OutputSchema = z.object({
51
+ total: z.number().nonnegative(),
52
+ items: z.array(z.string()).min(1),
53
+ });
54
+
55
+ // For input-dependent validation, use refinement in function
56
+ function process(items: string[]): z.infer<typeof OutputSchema> {
57
+ const result = { total: items.length, items };
58
+ return OutputSchema.parse(result);
59
+ }
60
+ ```
61
+
62
+ ### JSDoc Examples
63
+
64
+ ```typescript
65
+ /**
66
+ * Calculate doubled value.
67
+ * @example calculate(5) // => 10
68
+ * @example calculate(0) // => 0 (edge case)
69
+ */
70
+ function calculate(x: number): number {
71
+ return x * 2;
72
+ }
73
+ ```
@@ -0,0 +1,48 @@
1
+ ## Markers (TypeScript)
2
+
3
+ ### Entry Points
4
+
5
+ Entry points are framework callbacks (Express routes, Next.js handlers) at Shell boundary.
6
+ - **Exempt** from `Result<T, E>` — must match framework signature
7
+ - **Keep thin** (max 15 lines) — delegate to Shell functions that return Result
8
+
9
+ For custom callbacks:
10
+
11
+ ```typescript
12
+ // @shell:entry
13
+ export function onCustomEvent(data: Record<string, unknown>): Response {
14
+ const result = handleEvent(data);
15
+ if (result.isErr()) {
16
+ return new Response(JSON.stringify({ error: result.error }), { status: 500 });
17
+ }
18
+ return new Response(JSON.stringify(result.value));
19
+ }
20
+ ```
21
+
22
+ ### Shell Complexity
23
+
24
+ When shell function complexity is justified:
25
+
26
+ ```typescript
27
+ // @shell_complexity: External process with error classification
28
+ async function runExternalTool(...): Promise<Result<Output, Error>> { ... }
29
+
30
+ // @shell_orchestration: Multi-step pipeline coordination
31
+ async function processBatch(...): Promise<Result<BatchResult, Error>> { ... }
32
+ ```
33
+
34
+ ### Architecture Escape Hatch
35
+
36
+ When rule violation has valid architectural justification:
37
+
38
+ ```typescript
39
+ // @invar:allow shell_result: Express middleware signature fixed
40
+ function expressMiddleware(req: Request, res: Response, next: NextFunction): void { ... }
41
+ ```
42
+
43
+ **Valid rule names for @invar:allow:**
44
+ - `shell_result` — Shell function without Result return type
45
+ - `entry_point_too_thick` — Entry point exceeds 15 lines
46
+ - `forbidden_import` — I/O import in Core (rare, justify carefully)
47
+
48
+ Run `invar rules` for complete rule catalog with hints.
@@ -0,0 +1,65 @@
1
+ ## Commands (TypeScript)
2
+
3
+ ```bash
4
+ # Verification (Python CLI - works for TypeScript)
5
+ invar guard # Full: tsc + eslint + vitest + ts-analyzer
6
+ invar guard --json # Agent-friendly v2.0 JSON output
7
+ invar guard --changed # Modified files only
8
+
9
+ # Analysis
10
+ invar sig <file> # Show function signatures
11
+ invar map --top 10 # Most-referenced symbols
12
+ ```
13
+
14
+ ## Guard Output (v2.0 JSON)
15
+
16
+ ```json
17
+ {
18
+ "version": "2.0",
19
+ "language": "typescript",
20
+ "status": "passed",
21
+ "contracts": {
22
+ "coverage": {"total": 10, "withContracts": 7, "percent": 70},
23
+ "quality": {"strong": 3, "medium": 2, "weak": 1, "useless": 0},
24
+ "blind_spots": [
25
+ {"function": "deleteUser", "risk": "high", "suggested_schema": "z.object({...})"}
26
+ ]
27
+ }
28
+ }
29
+ ```
30
+
31
+ ## Configuration (TypeScript)
32
+
33
+ ```json
34
+ // package.json
35
+ {
36
+ "scripts": {
37
+ "build": "tsc",
38
+ "test": "vitest run",
39
+ "lint": "eslint src/"
40
+ }
41
+ }
42
+ ```
43
+
44
+ ```javascript
45
+ // vitest.config.ts
46
+ import { defineConfig } from 'vitest/config';
47
+
48
+ export default defineConfig({
49
+ test: {
50
+ include: ['src/**/*.test.ts', 'src/**/*.property.ts'],
51
+ },
52
+ });
53
+ ```
54
+
55
+ ## Embedded Node Tools
56
+
57
+ Invar includes bundled TypeScript analysis tools (no npm install required):
58
+
59
+ | Tool | Purpose |
60
+ |------|---------|
61
+ | **ts-analyzer** | Contract coverage, blind spot detection |
62
+ | **fc-runner** | Property-based testing with fast-check |
63
+ | **quick-check** | Fast pre-commit verification (<1s) |
64
+
65
+ These are called automatically by `invar guard` when analyzing TypeScript projects.
@@ -0,0 +1,104 @@
1
+ ## Troubleshooting (TypeScript)
2
+
3
+ ### Guard Output Interpretation
4
+
5
+ ```json
6
+ {
7
+ "status": "failed",
8
+ "contracts": {
9
+ "coverage": {"total": 10, "withContracts": 5, "percent": 50},
10
+ "blind_spots": [
11
+ {"function": "deleteUser", "risk": "high", "suggested_schema": "z.object({userId: z.string()})"}
12
+ ]
13
+ }
14
+ }
15
+ ```
16
+
17
+ | Field | Meaning | Action |
18
+ |-------|---------|--------|
19
+ | `status: failed` | Verification errors | Fix tsc/eslint/test errors first |
20
+ | `coverage.percent < 70` | Low contract coverage | Add Zod schemas to uncovered functions |
21
+ | `blind_spots` (high risk) | Critical functions without contracts | Priority: add schemas before next commit |
22
+ | `blind_spots` (medium risk) | Functions that should have contracts | Add schemas when modifying |
23
+
24
+ ### Fixing Blind Spots
25
+
26
+ ```typescript
27
+ // Before: blind spot (no validation)
28
+ function deleteUser(userId: string): void {
29
+ db.delete(userId);
30
+ }
31
+
32
+ // After: contract added
33
+ const DeleteUserInput = z.object({
34
+ userId: z.string().uuid(),
35
+ });
36
+
37
+ function deleteUser(input: z.infer<typeof DeleteUserInput>): void {
38
+ const { userId } = DeleteUserInput.parse(input);
39
+ db.delete(userId);
40
+ }
41
+ ```
42
+
43
+ ### Size Limits (Agent Quick Reference)
44
+
45
+ | Rule | Limit | Fix |
46
+ |------|-------|-----|
47
+ | `function_too_long` | **50 lines** | Extract helper: `_impl()` + main with JSDoc |
48
+ | `file_too_long` | **500 lines** | Split by responsibility |
49
+ | `entry_point_too_thick` | **15 lines** | Delegate to Shell functions |
50
+
51
+ *JSDoc/comment lines excluded from counts.*
52
+
53
+ ### Common Errors
54
+
55
+ | Symptom | Cause | Fix |
56
+ |---------|-------|-----|
57
+ | `ZodError` at runtime | Schema mismatch | Check input against Zod schema |
58
+ | `shell_result` error | Shell func no Result | Add Result<T,E> or @invar:allow |
59
+ | `isErr()` not found | Wrong Result import | Use `neverthrow` Result type |
60
+
61
+ ### Result Type Usage
62
+
63
+ ```typescript
64
+ import { Result, ok, err } from 'neverthrow';
65
+
66
+ // Creating results
67
+ return ok(value);
68
+ return err(error);
69
+
70
+ // Checking results
71
+ if (result.isErr()) {
72
+ handleError(result.error);
73
+ } else {
74
+ useValue(result.value);
75
+ }
76
+
77
+ // Chaining
78
+ result
79
+ .map(transform)
80
+ .andThen(nextOperation);
81
+
82
+ // Async operations
83
+ import { ResultAsync } from 'neverthrow';
84
+
85
+ const asyncResult = ResultAsync.fromPromise(
86
+ fetch(url),
87
+ (e) => new Error(`Fetch failed: ${e}`)
88
+ );
89
+ ```
90
+
91
+ ### Zod Validation Patterns
92
+
93
+ ```typescript
94
+ import { z } from 'zod';
95
+
96
+ // Safe parse (returns Result-like object)
97
+ const parsed = Schema.safeParse(data);
98
+ if (!parsed.success) {
99
+ console.error(parsed.error.issues);
100
+ }
101
+
102
+ // Strict parse (throws on error)
103
+ const validated = Schema.parse(data);
104
+ ```
@@ -0,0 +1,36 @@
1
+ ## Core/Shell Architecture
2
+
3
+ | Zone | Location | Requirements |
4
+ |------|----------|--------------|
5
+ | Core | `**/core/**` | Contracts + Examples, pure (no I/O) |
6
+ | Shell | `**/shell/**` | Error-handling return type |
7
+
8
+ ### Decision Tree: Core vs Shell
9
+
10
+ ```
11
+ Does this function...
12
+
13
+ ├─ Read or write files? ──────────────────→ Shell
14
+ ├─ Make network requests? ─────────────────→ Shell
15
+ ├─ Access current time? ──────────────────→ Shell OR inject as parameter
16
+ ├─ Generate random values? ────────────────→ Shell OR inject as parameter
17
+ ├─ Print to console? ──────────────────────→ Shell (return data, Shell logs)
18
+ ├─ Access environment variables? ──────────→ Shell
19
+
20
+ └─ None of the above? ─────────────────────→ Core
21
+ ```
22
+
23
+ ### Injection Pattern (Universal)
24
+
25
+ Instead of accessing impure values directly, inject them as parameters:
26
+
27
+ ```
28
+ # Core: receives 'current_time' as parameter (pure)
29
+ FUNCTION is_expired(expiry, current_time):
30
+ RETURN current_time > expiry
31
+
32
+ # Shell: calls with actual time
33
+ expired = is_expired(token.expiry, get_current_time())
34
+ ```
35
+
36
+ This keeps Core functions pure and testable.
@@ -0,0 +1,14 @@
1
+ ## Task Completion
2
+
3
+ A task is complete only when ALL conditions are met:
4
+ - Check-In displayed: `✓ Check-In: [project] | [branch] | [clean/dirty]`
5
+ - Intent explicitly stated
6
+ - Contract written before implementation
7
+ - Final displayed: `✓ Final: verification PASS | <errors>, <warnings>`
8
+ - User requirement satisfied
9
+
10
+ **Missing any = Task incomplete.**
11
+
12
+ ---
13
+
14
+ *Protocol v5.0 — USBV workflow | [Examples](.invar/examples/)*
@@ -0,0 +1,37 @@
1
+ ## Contract Concepts
2
+
3
+ ### Precondition
4
+ Constraints on inputs that must be true before function executes.
5
+
6
+ ```
7
+ PRECONDITION: input_value > 0 AND input_value < 100
8
+ ```
9
+
10
+ ### Postcondition
11
+ Guarantees about outputs that must be true after function executes.
12
+
13
+ ```
14
+ POSTCONDITION: result >= 0
15
+ ```
16
+
17
+ ### Self-Test Rule
18
+
19
+ > "Can someone else write the exact same function from just the contracts + examples?"
20
+
21
+ If yes → Contracts are complete.
22
+ If no → Add more constraints or examples.
23
+
24
+ ### Meaningful Contracts
25
+
26
+ Contracts should check **business logic**, not just types:
27
+
28
+ ```
29
+ # Redundant - type system already checks this
30
+ PRECONDITION: x is integer
31
+
32
+ # Meaningful - checks business logic
33
+ PRECONDITION: x > 0
34
+
35
+ # Meaningful - checks relationship between params
36
+ PRECONDITION: start < end
37
+ ```
@@ -0,0 +1,17 @@
1
+ <!--
2
+ ┌─────────────────────────────────────────────────────────────┐
3
+ │ INVAR-MANAGED FILE - DO NOT EDIT DIRECTLY │
4
+ │ │
5
+ │ This file is managed by Invar. Changes may be lost on │
6
+ │ `invar update`. Add project content to CLAUDE.md instead. │
7
+ └─────────────────────────────────────────────────────────────┘
8
+
9
+ License: CC-BY-4.0 (Creative Commons Attribution 4.0 International)
10
+ https://creativecommons.org/licenses/by/4.0/
11
+
12
+ You are free to share and adapt this document, provided you give
13
+ appropriate credit to the Invar project.
14
+ -->
15
+ # The Invar Protocol v5.0
16
+
17
+ > **"Trade structure for safety."**
@@ -0,0 +1,17 @@
1
+ ## Check-In (Required)
2
+
3
+ Your first message MUST display:
4
+
5
+ ```
6
+ ✓ Check-In: [project] | [branch] | [clean/dirty]
7
+ ```
8
+
9
+ Actions:
10
+ 1. Read `.invar/context.md` (Key Rules + Current State + Lessons Learned)
11
+ 2. Show one-line status
12
+
13
+ **Do NOT execute verification at Check-In.**
14
+ Verification is for VALIDATE phase and Final only.
15
+
16
+ This is your sign-in. The user sees it immediately.
17
+ No visible check-in = Session not started.
@@ -0,0 +1,10 @@
1
+ ## Six Laws
2
+
3
+ | Law | Principle |
4
+ |-----|-----------|
5
+ | 1. Separation | Core (pure logic) / Shell (I/O) physically separate |
6
+ | 2. Contract Complete | Preconditions + Postconditions + Examples uniquely determine implementation |
7
+ | 3. Context Economy | Overview → Signatures → Code (only read what's needed) |
8
+ | 4. Decompose First | Break into sub-functions before implementing |
9
+ | 5. Verify Reflectively | Fail → Reflect (why?) → Fix → Verify |
10
+ | 6. Integrate Fully | Local correct ≠ Global correct; verify all paths |
@@ -0,0 +1,14 @@
1
+ ## USBV Workflow
2
+
3
+ **U**nderstand → **S**pecify → **B**uild → **V**alidate
4
+
5
+ | Phase | Purpose | Activities |
6
+ |-------|---------|------------|
7
+ | UNDERSTAND | Know what and why | Intent, Inspect existing code, Constraints |
8
+ | SPECIFY | Define boundaries | Preconditions, Postconditions, Examples |
9
+ | BUILD | Write code | Implement leaves, Compose |
10
+ | VALIDATE | Confirm correctness | Run verification, Review if needed |
11
+
12
+ **Key:** Inspect before Contract. Contracts before Code. Depth varies naturally.
13
+
14
+ **Review Gate:** When verification triggers `review_suggested` (escape hatches ≥3, security paths, low coverage), invoke `/review` before completion.
@@ -0,0 +1,25 @@
1
+ ## Visible Workflow
2
+
3
+ For complex tasks (3+ functions), show 3 checkpoints in TodoList:
4
+
5
+ ```
6
+ □ [UNDERSTAND] Task description, codebase context, constraints
7
+ □ [SPECIFY] Contracts and design decomposition
8
+ □ [VALIDATE] Verification results, Review Gate if triggered, integration status
9
+ ```
10
+
11
+ **BUILD is internal work** — not shown in TodoList.
12
+
13
+ **Show contracts before code.** Example:
14
+
15
+ ```
16
+ [SPECIFY] calculate_discount:
17
+ PRECONDITION: price > 0 AND 0 <= rate <= 1
18
+ POSTCONDITION: result >= 0
19
+ FUNCTION calculate_discount(price, rate): ...
20
+
21
+ [BUILD] Now coding...
22
+ ```
23
+
24
+ **When to use:** New features (3+ functions), architectural changes, Core modifications.
25
+ **Skip for:** Single-line fixes, documentation, trivial refactoring.