jcl 1.2.0

Jack-of-All Configuration Language - A general-purpose configuration language with powerful built-in functions
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
# CLAUDE.md - AI Assistant Development Guide

This document provides comprehensive guidance for AI assistants (primarily Claude) working on the JCL project. It covers the current state of the language, design decisions, development workflow, and coding standards.

## Table of Contents

1. [Project Overview]#project-overview
2. [Language Design & Current State]#language-design--current-state
3. [Architecture & Components]#architecture--components
4. [Development Workflow]#development-workflow
5. [Testing Requirements]#testing-requirements
6. [Code Style & Standards]#code-style--standards
7. [Issue & PR Templates]#issue--pr-templates
8. [Common Pitfalls]#common-pitfalls

---

## Project Overview

**JCL (Jack-of-All Configuration Language)** is a general-purpose configuration language with:
- **Version**: 1.2.0 (major feature release with cross-compilation, heredocs, splat, range syntax)
- **Language**: Rust (edition 2021)
- **Status**: 297 tests passing, zero warnings
- **License**: MIT OR Apache-2.0

### Project Goals

1. **Human-readable**: Clean syntax with minimal punctuation
2. **Type-safe**: Advanced static type inference + runtime validation
3. **Powerful**: 76+ built-in functions including streaming & higher-order functions
4. **Embeddable**: Multi-language bindings (Python, Node.js, Go, Java, Ruby)
5. **Tooling**: Complete ecosystem (LSP, formatter, linter, validator, migrator)
6. **Performant**: Transparent lazy evaluation for memory-efficient operations

### What JCL Is NOT

- **NOT** a full programming language (intentionally constrained)
- **NOT** infrastructure-specific (removed Terraform-like features in favor of general-purpose design)
- **NOT** dynamically typed (has advanced static type inference)

---

## Language Design & Current State

### Syntax Overview

#### Collections

```jcl
# Lists use square brackets
numbers = [1, 2, 3, 4, 5]
names = ["Alice", "Bob", "Carol"]

# Maps use parentheses with commas separating entries
config = (
    host = "localhost",
    port = 8080,
    enabled = true
)

# IMPORTANT: Multi-line maps REQUIRE commas
# This is WRONG:
bad_map = (
    host = "localhost"
    port = 8080
)

# This is CORRECT:
good_map = (
    host = "localhost",
    port = 8080
)
```

#### String Interpolation

```jcl
name = "World"
greeting = "Hello, ${name}!"
expression = "2 + 2 = ${2 + 2}"
```

#### Functions

```jcl
# Lambda functions
double = x => x * 2
add = (x, y) => x + y

# Named functions
fn triple(n) = n * 3
fn greet(name) = "Hello, ${name}!"

# Calling functions
result = double(21)  # 42
```

#### List Comprehensions

```jcl
# Python-style list comprehensions
doubled = [x * 2 for x in numbers]
filtered = [x for x in numbers if x > 2]

# IMPORTANT: JCL does NOT support standalone for loops
# This is WRONG:
# for x in list do something

# Use list comprehensions instead:
# results = [something(x) for x in list]
```

#### Null Safety

```jcl
# Optional chaining
value = config?.database?.host  # Returns null if any part is null

# Null coalescing
port = config?.port ?? 8080  # Use 8080 if port is null
```

#### Control Flow

```jcl
# Ternary operator
status = x > 0 ? "positive" : "negative"

# If/then/else expression
result = if x > 0 then "positive" else "negative"

# When expression (pattern matching)
grade = when score {
    >= 90 => "A"
    >= 80 => "B"
    >= 70 => "C"
    else => "F"
}
```

#### Error Handling

```jcl
# Try function for graceful error recovery
result = try(risky_operation(), "default_value")

# Error handling is expression-level, not statement-level
```

### Type System

#### Static Type Inference

JCL has **Hindley-Milner style type inference** that catches errors before runtime:

```rust
// In src/types.rs
pub struct TypeChecker {
    env: TypeEnvironment,
    errors: Vec<TypeError>,
}

impl TypeChecker {
    pub fn check_module(&mut self, module: &Module) -> Result<(), Vec<TypeError>>
    pub fn infer_expression(&self, expr: &Expression) -> Result<Type, TypeError>
}
```

**Key Points**:
- Type checking happens **before** evaluation
- Expression-level type checking (every expression has an inferred type)
- Type errors include precise source spans (line, column, length)
- 70+ built-in functions have type signatures pre-registered

#### Type Annotations

```jcl
# Optional type annotations for documentation/validation
x: Int = 42
name: String = "Alice"
config: Map = (host = "localhost", port = 8080)
```

### Built-in Functions (76+)

Organized in categories in `src/functions.rs`:

1. **String**: `upper`, `lower`, `trim`, `replace`, `split`, `join`, `format`, `substr`, `startswith`, `endswith`, `contains`
2. **Encoding**: `jsonencode`, `jsondecode`, `yamlencode`, `yamldecode`, `toml encode`, `tomldecode`, `base64encode`, `base64decode`, `urlencode`, `urldecode`
3. **Collections**: `merge`, `lookup`, `keys`, `values`, `length`, `sort`, `reverse`, `distinct`, `flatten`, `zip`, `contains`, `concat`
4. **Higher-Order**: `map`, `filter`, `reduce` (polymorphic: work with both lists and streams)
5. **Streaming** ⭐ NEW: `stream`, `take`, `collect` (lazy evaluation for memory efficiency)
6. **Numeric**: `min`, `max`, `sum`, `avg`, `abs`, `ceil`, `floor`, `round`, `pow`, `sqrt`
7. **Hashing**: `md5`, `sha1`, `sha256`, `sha512`
8. **Filesystem**: `file`, `fileexists`, `dirname`, `basename`, `pathexpand`
9. **Templating**: `template`, `templatefile` (uses Handlebars)
10. **Type Conversion**: `tostring`, `tonumber`, `tobool`, `totype`
11. **Time**: `timestamp`, `formatdate`, `timeadd`
12. **Validation**: `regex`, `regexreplace`
13. **Error Handling**: `try`

### Transparent Lazy Evaluation ⭐ NEW in v1.1.0

JCL automatically optimizes list comprehensions with slicing:

```jcl
# Automatically optimized! Only processes first 10 elements, not all 1000.
result = [x * 2 for x in [0..1000]][0:10]
# [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
```

**Pattern detected**: `[expr for x in list][start:end]` or `[expr for x in list if cond][start:end]`

**Benefits**:
- **Memory**: O(k) instead of O(n) where k = slice size
- **Speed**: Only processes what's needed (10x-100x faster for small slices)
- **Transparent**: No code changes required

See `src/evaluator.rs:625-672` for pattern detection and `src/evaluator.rs:1400-1470` for lazy evaluation implementation.

---

## Architecture & Components

### File Structure

```
src/
├── lib.rs              # Public API exports
├── main.rs             # CLI entry point (jcl binary)
├── lexer.pest          # PEG grammar for tokenization
├── lexer.rs            # Lexer implementation
├── parser.rs           # Original parser (being phased out)
├── token_parser.rs     # New Pratt parser for expressions
├── ast.rs              # Abstract Syntax Tree definitions
├── types.rs            # Type system (inference, checking, environment)
├── evaluator.rs        # Expression evaluation engine
├── functions.rs        # All built-in functions
├── formatter.rs        # Code formatter (jcl-fmt)
├── linter.rs           # Linting rules and diagnostics
├── lsp.rs              # Language Server Protocol implementation
├── repl.rs             # Interactive REPL
├── schema.rs           # Schema validation
├── migration.rs        # Format migration (JSON/YAML/TOML -> JCL)
├── symbol_table.rs     # Symbol tracking for LSP (go-to-def, references)
├── docgen.rs           # Documentation generator
├── bin/                # CLI tools
│   ├── jcl-lsp.rs
│   ├── jcl-fmt.rs
│   ├── jcl-validate.rs
│   ├── jcl-migrate.rs
│   ├── jcl-watch.rs
│   └── jcl-bench.rs
└── bindings/           # Multi-language bindings
    ├── ffi.rs          # C FFI
    ├── wasm.rs         # WebAssembly
    ├── python.rs       # PyO3
    ├── nodejs.rs       # Neon
    ├── java.rs         # JNI
    └── ruby.rs         # Magnus
```

### Key Data Structures

#### AST (src/ast.rs)

```rust
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Module {
    pub statements: Vec<Statement>,
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Statement {
    Assignment { name: String, value: Expression, type_annotation: Option<Type>, span: Option<SourceSpan>, doc_comments: Vec<String> },
    FunctionDef { name: String, params: Vec<Parameter>, return_type: Option<Type>, body: Expression, span: Option<SourceSpan>, doc_comments: Vec<String> },
    Import { path: String, alias: Option<String>, span: Option<SourceSpan> },
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub enum Expression {
    Literal(Value),
    Identifier(String),
    Binary { left: Box<Expression>, op: BinaryOperator, right: Box<Expression>, span: Option<SourceSpan> },
    Unary { op: UnaryOperator, operand: Box<Expression>, span: Option<SourceSpan> },
    FunctionCall { name: String, args: Vec<Expression>, span: Option<SourceSpan> },
    Lambda { params: Vec<String>, body: Box<Expression>, span: Option<SourceSpan> },
    // ... many more variants
}
```

#### Type Environment (src/types.rs)

```rust
#[derive(Debug, Clone)]
pub struct TypeEnvironment {
    variables: HashMap<String, Type>,
    functions: HashMap<String, Type>,
    parent: Option<Box<TypeEnvironment>>,
}

impl TypeEnvironment {
    pub fn new() -> Self { /* ... */ }
    pub fn child(&self) -> Self { /* Creates nested scope */ }
    pub fn register_builtins(&mut self) { /* Registers 70+ function signatures */ }
    pub fn define_variable(&mut self, name: String, ty: Type) { /* ... */ }
    pub fn lookup_variable(&self, name: &str) -> Option<Type> { /* Searches up parent chain */ }
}
```

---

## Development Workflow

### 1. NEVER Push Directly to Main

**CRITICAL RULE**: NEVER push commits directly to the `main` branch.

**ALWAYS follow this workflow**:

```bash
# ❌ NEVER DO THIS:
git push origin main

# ✅ ALWAYS DO THIS:
# 1. Create a feature branch
git checkout -b feature/your-feature-name

# 2. Make changes and commit
git add .
git commit -m "Your commit message"

# 3. Push to feature branch
git push origin feature/your-feature-name

# 4. Create an issue first (if not exists)
gh issue create --title "..." --body "..."

# 5. Create a pull request referencing the issue
gh pr create --title "..." --body "Closes #XX ..."
```

**Why this matters**:
- Maintains code review process
- Enables CI/CD checks before merging
- Creates audit trail via issues and PRs
- Prevents accidental breaking changes
- Allows for discussion and collaboration

**Exception**: There are NO exceptions. Even trivial changes must go through PR process.

### 2. Always Read Files First

**CRITICAL**: Always use the `Read` tool before `Edit` or `Write`:

```
❌ WRONG:
Edit tool without reading first

✅ CORRECT:
1. Read the file
2. Analyze the content
3. Edit with precise old_string/new_string
```

### 3. Pre-commit Hooks (Automated Quality Checks)

**RECOMMENDED**: Install the pre-commit hooks to automatically run quality checks:

```bash
./scripts/install-hooks.sh
```

Once installed, the pre-commit hook will **automatically** run these checks before every commit:
- `cargo fmt --all` - Auto-format code
- `cargo clippy --lib --tests --bins --all-features` - Check for warnings
- `cargo test` - Run all tests

**Benefits**:
- ✅ Prevents committing code that fails CI
- ✅ Automatically formats code (no manual `cargo fmt` needed)
- ✅ Catches issues locally before they reach the repository
- ✅ Saves time and reduces CI failures

**If hooks are not installed** (manual checklist):

```bash
# REQUIRED BEFORE EVERY COMMIT (in this order):

# 0. Check git status for unwanted files
git status
# Ensure .venv/, __pycache__/, target/, etc. are NOT in "Changes to be committed"
# Update .gitignore if needed before committing

# 1. Format code
cargo fmt --all

# 2. Check formatting is correct
cargo fmt --all -- --check

# 3. Run all tests
cargo test

# 4. Check for clippy warnings
cargo clippy --lib --tests --bins --all-features

# CRITICAL: If any of these fail, DO NOT commit. Fix the issues first.
```

**Bypassing the hook** (when absolutely necessary):
```bash
git commit --no-verify  # Use sparingly - may cause CI failures
```

**Test counts (as of v1.0.0)**:
- Unit tests: 117
- CLI integration tests: 18
- Integration tests: 9
- **Total: 297 tests** (144 original + 6 Phase 2 streaming + 8 Phase 3 transparent optimization + other additions)

### 4. Incremental Development

```
1. Read relevant files
2. Make small, focused changes
3. Test immediately
4. Fix any errors
5. Repeat
```

### 5. Preserve Exact Indentation

When using `Edit` tool:
- **DO NOT** include line number prefixes in `old_string` or `new_string`
- **PRESERVE** exact indentation (tabs vs spaces)
- Match existing code style

Example:
```rust
// CORRECT old_string (no line numbers, exact indentation):
    pub fn check_module(&mut self, module: &Module) -> Result<(), Vec<TypeError>> {
        for statement in &module.statements {
            self.check_statement(statement)?;
        }
        Ok(())
    }
```

### 6. Handle Pattern Matching Carefully

Rust pattern matching requires all fields unless using `..`:

```rust
// If struct has more fields than you're matching:
Statement::FunctionDef {
    name,
    params,
    body,
    ..  // Ignore remaining fields
} => { /* ... */ }
```

---

## Testing Requirements

### Unit Tests

Located in each source file (e.g., `src/types.rs`):

```rust
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_type_inference() {
        // Arrange
        let expr = Expression::Literal(Value::Int(42));
        let checker = TypeChecker::new();

        // Act
        let result = checker.infer_expression(&expr);

        // Assert
        assert_eq!(result.unwrap(), Type::Int);
    }
}
```

### CLI Integration Tests

Located in `tests/cli_tests.rs`:

```rust
#[test]
fn test_jcl_eval_basic() {
    let jcl_path = get_binary_path("jcl");
    let test_file = create_temp_file(
        "test.jcf",
        r#"
x = 42
y = "hello"
"#,
    );

    let output = Command::new(&jcl_path)
        .arg("eval")
        .arg(&test_file)
        .output()
        .expect("Failed to execute jcl eval");

    assert!(output.status.success());
    let stdout = String::from_utf8_lossy(&output.stdout);
    assert!(stdout.contains("x = 42"));
}
```

**Key Helpers**:
```rust
fn get_binary_path(name: &str) -> String { /* ... */ }
fn create_temp_file(name: &str, content: &str) -> String { /* ... */ }
```

### Test Syntax Correctness

When writing test JCL code:

✅ **Correct**:
```jcl
# Maps with commas
config = (host = "localhost", port = 8080)

# List comprehensions (not for loops)
doubled = [x * 2 for x in numbers]

# Lists for indexing
numbers = [1, 2, 3]
first = numbers[0]
```

❌ **Incorrect**:
```jcl
# Maps without commas (FAILS)
config = (
    host = "localhost"
    port = 8080
)

# Standalone for loops (NOT SUPPORTED)
for x in numbers do print(x)
```

---

## Code Style & Standards

### Rust Style

```rust
// Use cargo fmt default settings
// Run before committing:
cargo fmt

// Check with clippy:
cargo clippy
```

### Error Messages

Provide helpful, contextual error messages:

```rust
// GOOD:
return Err(TypeError {
    message: format!(
        "Type mismatch: expected {}, found {} at {}:{}",
        expected, found, span.line, span.column
    ),
    span: Some(span.clone()),
});

// BAD:
return Err(TypeError {
    message: "Type error".to_string(),
    span: None,
});
```

### Span Information

**ALWAYS** include source spans for diagnostics:

```rust
#[derive(Debug, Clone)]
pub struct SourceSpan {
    pub line: usize,
    pub column: usize,
    pub offset: usize,
    pub length: usize,
}
```

This enables:
- Precise error messages
- LSP diagnostics with exact locations
- Better developer experience

### Documentation

Use rustdoc comments:

```rust
/// Checks the type of an expression and returns the inferred type.
///
/// # Arguments
///
/// * `expr` - The expression to type check
///
/// # Returns
///
/// Returns `Ok(Type)` with the inferred type, or `Err(TypeError)` if type checking fails.
///
/// # Examples
///
/// ```
/// let expr = Expression::Literal(Value::Int(42));
/// let ty = checker.infer_expression(&expr)?;
/// assert_eq!(ty, Type::Int);
/// ```
pub fn infer_expression(&self, expr: &Expression) -> Result<Type, TypeError> {
    // Implementation
}
```

---

## Issue & PR Templates

### When Creating Issues

Use the appropriate template:

1. **Bug Report** (`.github/ISSUE_TEMPLATE/bug_report.md`):
   - Clear description
   - Steps to reproduce
   - Minimal reproducible example
   - Expected vs actual behavior
   - Environment details

2. **Feature Request** (`.github/ISSUE_TEMPLATE/feature_request.md`):
   - Problem description
   - Proposed solution
   - Alternatives considered
   - Use cases

3. **Documentation** (`.github/ISSUE_TEMPLATE/documentation.md`):
   - What's missing/incorrect
   - Where it should be documented
   - Suggested improvements

### When Creating PRs

Follow the template (`.github/PULL_REQUEST_TEMPLATE.md`):

**Required Sections**:
```markdown
## Description
[Clear description of changes]

## Type of Change
- [x] Bug fix / New feature / etc.

## Testing
- [x] All existing tests pass
- [x] Added new tests
- [x] Tested manually

## Checklist
- [x] Ran cargo fmt
- [x] Ran cargo clippy
- [x] Updated documentation
- [x] No new warnings
```

**CRITICAL Checklist Items**:
1. ✅ All existing tests pass (`cargo test`)
2. ✅ Code formatted (`cargo fmt`)
3. ✅ No clippy warnings (`cargo clippy`)
4. ✅ Documentation updated (if needed)
5. ✅ No new compiler warnings

### Issue and PR Metadata

**ALWAYS** add appropriate labels when creating issues or PRs using the `--label` flag with `gh issue create` or `gh pr create`.

#### Label Categories

**Type Labels** (choose one):
- `bug` - Something isn't working
- `enhancement` - New feature or request
- `documentation` - Documentation improvements
- `question` - Further information is requested
- `type: testing` - Testing-related changes
- `type: breaking-change` - Breaking API changes
- `type: performance` - Performance improvements
- `type: refactor` - Code refactoring

**Area Labels** (choose one or more as applicable):
- `area: parser` - Lexer, token parsing
- `area: type-system` - Type inference, type checking
- `area: cli-tools` - CLI tools (fmt, validate, migrate, etc)
- `area: evaluator` - Expression evaluation, runtime
- `area: lsp` - Language Server Protocol
- `area: bindings` - Multi-language bindings (general)
- `area: ffi` - C Foreign Function Interface
- `area: formatter` - Code formatter (jcl-fmt)
- `area: wasm` - WebAssembly support
- `area: linter` - Linting rules and diagnostics
- `area: repl` - Interactive REPL
- `area: validator` - Schema validation (jcl-validate)

**Language-Specific Bindings** (if applicable):
- `lang: go` - Go bindings (cgo)
- `lang: nodejs` - Node.js bindings (Neon)
- `lang: python` - Python bindings (PyO3)
- `lang: java` - Java bindings (JNI)
- `lang: ruby` - Ruby bindings (Magnus)

#### Examples

```bash
# Bug in parser
gh issue create --title "Parser fails on nested maps" \
  --body "..." \
  --label "bug,area: parser"

# Enhancement for Python bindings
gh issue create --title "Add async support to Python bindings" \
  --body "..." \
  --label "enhancement,area: bindings,lang: python"

# Documentation for LSP
gh issue create --title "Document LSP configuration options" \
  --body "..." \
  --label "documentation,area: lsp"

# PR for type system refactor
gh pr create --title "Refactor type inference engine" \
  --body "..." \
  --label "type: refactor,area: type-system"
```

**Guidelines**:
- Always include at least one type label (`bug`, `enhancement`, `documentation`, etc.)
- Add relevant area labels to help categorize the issue/PR
- Add language-specific labels when working on bindings
- Multiple labels are encouraged for better organization
- Labels help with project management and filtering

---

## Common Pitfalls

### 1. Map Syntax Without Commas

❌ **Wrong**:
```jcl
config = (
    host = "localhost"
    port = 8080
)
```

✅ **Correct**:
```jcl
config = (host = "localhost", port = 8080)
```

### 2. Using For Loops Instead of List Comprehensions

❌ **Wrong**:
```jcl
for x in numbers do print(x)
```

✅ **Correct**:
```jcl
results = [process(x) for x in numbers]
```

### 3. Forgetting to Register Built-in Function Types

When adding a new built-in function in `src/functions.rs`, also add its type signature in `src/types.rs`:

```rust
// In TypeEnvironment::register_builtins()
self.define_function("new_function".to_string(), Type::Function {
    params: vec![Type::String],
    return_type: Box::new(Type::String),
});
```

### 4. Not Including Spans in Errors

Always include source spans:

```rust
// GOOD:
LintIssue {
    severity: Severity::Error,
    message: "Undefined variable".to_string(),
    rule: "no-undefined-vars".to_string(),
    suggestion: Some("Did you mean 'count'?".to_string()),
    span: Some(expr.span.clone()),  // ✅ Includes span
}

// BAD:
LintIssue {
    /* ... */
    span: None,  // ❌ No span
}
```

### 5. Editing Files Without Reading Them First

The `Edit` tool will fail if you haven't read the file in the current conversation:

```
✅ CORRECT workflow:
1. Read(file_path)
2. Analyze content
3. Edit(file_path, old_string, new_string)

❌ WRONG:
1. Edit(file_path, ...) ← FAILS
```

### 6. Not Testing After Changes

**ALWAYS** run tests after making changes:

```bash
# After editing src/types.rs:
cargo test --lib types

# After editing CLI tools:
cargo test --test cli_tests

# Before committing:
cargo test && cargo clippy && cargo fmt --check
```

### 7. Assuming Infrastructure Features Exist

JCL used to be infrastructure-focused but is now **general-purpose**. The following NO LONGER EXIST:

❌ Removed/Never Existed:
- Provider system
- State management
- Resource definitions
- Plan/apply workflow (beyond REPL)
- Hemmer-specific features

✅ What Exists:
- General-purpose configuration
- Built-in functions
- Type system
- Templating
- Import system

---

## Design Decisions & Rationale

### Why Parentheses for Maps?

**Decision**: Use `()` for maps, `[]` for lists

**Rationale**:
- Differentiates from JSON/YAML syntax
- More human-readable (less visual noise)
- Parentheses group related configuration naturally
- Square brackets indicate ordered collections

### Why No Standalone For Loops?

**Decision**: List comprehensions only, no `for...do` syntax

**Rationale**:
- JCL is a configuration language, not a general programming language
- List comprehensions are declarative (what to compute)
- For loops are imperative (how to compute)
- Simpler mental model for configuration

### Why Static Type Inference?

**Decision**: Hindley-Milner style type inference before evaluation

**Rationale**:
- Catch errors before runtime
- Better developer experience with LSP
- Type-safe without verbose annotations
- Safer for production configuration

### Why Multi-Language Bindings?

**Decision**: Support Python, Node.js, Go, Java, Ruby, WASM, C FFI

**Rationale**:
- JCL is designed to be embeddable
- Different ecosystems have different needs
- Increases adoption potential
- Rust makes FFI relatively straightforward

---

## When Working on JCL

### General Guidelines

1. **Read CHANGELOG.md** to understand recent changes
2. **Check existing tests** to understand expected behavior
3. **Follow existing patterns** in the codebase
4. **Test thoroughly** before proposing changes
5. **Document design decisions** for future reference

### For Language Changes

1. Update `src/lexer.pest` if changing syntax
2. Update `src/ast.rs` if changing AST
3. Update `src/parser.rs` or `src/token_parser.rs` for parsing
4. Update `src/types.rs` for type inference
5. Update `src/evaluator.rs` for evaluation
6. Add tests in relevant `mod tests` blocks
7. Update documentation in `docs/`

### For Built-in Functions

1. Add function to `src/functions.rs`
2. Add type signature to `TypeEnvironment::register_builtins()` in `src/types.rs`
3. Add tests in `src/functions.rs`
4. Document in `docs/reference/functions.md`
5. Add docstring comments for `docgen`

### For Tooling (LSP, Formatter, etc.)

1. Understand existing implementation first
2. Make incremental changes
3. Test with real editor integration
4. Update relevant documentation

---

## Summary

**Key Takeaways**:
1. **Always test** before committing
2.**Always read** files before editing
3. ✅ Use **correct JCL syntax** (commas in maps, list comprehensions not for loops)
4. ✅ Include **source spans** in all diagnostics
5. ✅ Follow **issue/PR templates** exactly
6.**Zero warnings** policy (cargo clippy)
7. ✅ Document **design decisions** in code comments
8. ✅ JCL is **general-purpose**, not infrastructure-specific

**Current State**:
- Version: 1.2.0
- Tests: 297 passing
- Warnings: 0
- Features: 90+ built-in functions including streaming API, heredocs, splat, range syntax
- New: Cross-compilation for 6 target platforms
- Ready for publication

**Resources**:
- Full docs: https://jcl.hemmer.io/
- Language spec: `docs/reference/language-spec.md`
- Function reference: `docs/reference/functions.md`
- Contributing: `CONTRIBUTING.md`

---

*Last Updated: 2025-11-24 for JCL v1.2.0 (Cross-compilation, Heredocs, Splat, Range Syntax, Module System)*