context_spook 1.5.1 → 1.7.0

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 (43) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +103 -12
  3. data/Rakefile +7 -8
  4. data/bin/context_spook +6 -3
  5. data/context_spook.gemspec +7 -8
  6. data/lib/context_spook/generator.rb +83 -45
  7. data/lib/context_spook/output_context.rb +13 -8
  8. data/lib/context_spook/toon/encoder.rb +628 -0
  9. data/lib/context_spook/toon/example.md +36 -66
  10. data/lib/context_spook/toon.rb +13 -15
  11. data/lib/context_spook/utils.rb +31 -4
  12. data/lib/context_spook/version.rb +1 -1
  13. data/spec/context_spook/generator_spec.rb +65 -1
  14. data/spec/context_spook/toon_encoder_spec.rb +90 -0
  15. data/spec/context_spook/toon_spec.rb +15 -16
  16. data/spec/examples/README.md +79 -0
  17. data/spec/examples/conversions/keyed-tabular-objects.json +19 -0
  18. data/spec/examples/conversions/keyed-tabular-objects.toon +4 -0
  19. data/spec/examples/conversions/nested-field-groups.json +28 -0
  20. data/spec/examples/conversions/nested-field-groups.toon +4 -0
  21. data/spec/examples/conversions/tabular-arrays.json +22 -0
  22. data/spec/examples/conversions/tabular-arrays.toon +4 -0
  23. data/spec/examples/invalid/delimiter-mismatch.toon +3 -0
  24. data/spec/examples/invalid/length-mismatch.toon +3 -0
  25. data/spec/examples/invalid/multiple-root-primitives.toon +2 -0
  26. data/spec/examples/valid/comments.toon +5 -0
  27. data/spec/examples/valid/delimiter-scoping.toon +5 -0
  28. data/spec/examples/valid/mixed-arrays.toon +5 -0
  29. data/spec/examples/valid/nested-objects.toon +9 -0
  30. data/spec/examples/valid/objects.toon +6 -0
  31. data/spec/examples/valid/pipe-delimiter.toon +3 -0
  32. data/spec/examples/valid/primitive-arrays.toon +3 -0
  33. data/spec/examples/valid/tab-delimiter.toon +3 -0
  34. data/spec/fixtures/encode/arrays-nested.json +120 -0
  35. data/spec/fixtures/encode/arrays-objects.json +160 -0
  36. data/spec/fixtures/encode/arrays-primitive.json +95 -0
  37. data/spec/fixtures/encode/arrays-tabular.json +182 -0
  38. data/spec/fixtures/encode/delimiters.json +214 -0
  39. data/spec/fixtures/encode/objects-keyed.json +160 -0
  40. data/spec/fixtures/encode/objects.json +288 -0
  41. data/spec/fixtures/encode/primitives.json +262 -0
  42. data/spec/fixtures/encode/whitespace.json +54 -0
  43. metadata +35 -18
@@ -0,0 +1,262 @@
1
+ {
2
+ "version": "4.0",
3
+ "category": "encode",
4
+ "description": "Primitive value encoding – strings, numbers, booleans, null",
5
+ "tests": [
6
+ {
7
+ "name": "encodes safe strings without quotes",
8
+ "input": "hello",
9
+ "expected": "hello",
10
+ "specSection": "7.2"
11
+ },
12
+ {
13
+ "name": "encodes safe string with underscore and numbers",
14
+ "input": "Ada_99",
15
+ "expected": "Ada_99",
16
+ "specSection": "7.2"
17
+ },
18
+ {
19
+ "name": "quotes empty string",
20
+ "input": "",
21
+ "expected": "\"\"",
22
+ "specSection": "7.2"
23
+ },
24
+ {
25
+ "name": "quotes string that looks like true",
26
+ "input": "true",
27
+ "expected": "\"true\"",
28
+ "specSection": "7.2"
29
+ },
30
+ {
31
+ "name": "quotes string that looks like false",
32
+ "input": "false",
33
+ "expected": "\"false\"",
34
+ "specSection": "7.2"
35
+ },
36
+ {
37
+ "name": "quotes string that looks like null",
38
+ "input": "null",
39
+ "expected": "\"null\"",
40
+ "specSection": "7.2"
41
+ },
42
+ {
43
+ "name": "quotes string that looks like integer",
44
+ "input": "42",
45
+ "expected": "\"42\"",
46
+ "specSection": "7.2"
47
+ },
48
+ {
49
+ "name": "quotes string that looks like a decimal",
50
+ "input": "3.14",
51
+ "expected": "\"3.14\"",
52
+ "specSection": "7.2"
53
+ },
54
+ {
55
+ "name": "quotes string that looks like scientific notation",
56
+ "input": "1e-6",
57
+ "expected": "\"1e-6\"",
58
+ "specSection": "7.2"
59
+ },
60
+ {
61
+ "name": "quotes string with leading zero",
62
+ "input": "05",
63
+ "expected": "\"05\"",
64
+ "specSection": "7.2",
65
+ "note": "Matches the numeric-like pattern, so it MUST be quoted"
66
+ },
67
+ {
68
+ "name": "escapes newline, tab, and carriage return in strings",
69
+ "input": ["line1\nline2", "tab\there", "return\rcarriage"],
70
+ "expected": "[3]: \"line1\\nline2\",\"tab\\there\",\"return\\rcarriage\"",
71
+ "specSection": "7.1"
72
+ },
73
+ {
74
+ "name": "escapes U+0004, U+0008, and U+000C via \\uXXXX and keeps DEL, U+0085, and U+2028 literal in quoted strings",
75
+ "input": { "val": "a\u0004\b\fb", "sep": "a:\u007f\u0085\u2028b" },
76
+ "expected": "val: \"a\\u0004\\u0008\\u000cb\"\nsep: \"a:\u007f\u0085\u2028b\"",
77
+ "specSection": "7.1",
78
+ "minSpecVersion": "4.2"
79
+ },
80
+ {
81
+ "name": "escapes backslash in string",
82
+ "input": "Users\\path",
83
+ "expected": "\"Users\\\\path\"",
84
+ "specSection": "7.1"
85
+ },
86
+ {
87
+ "name": "keeps a string with an interior hyphen or hash unquoted",
88
+ "input": "a-b #c",
89
+ "expected": "a-b #c",
90
+ "specSection": "7.2",
91
+ "minSpecVersion": "4.2"
92
+ },
93
+ {
94
+ "name": "quotes string starting with hyphen-space",
95
+ "input": "- item",
96
+ "expected": "\"- item\"",
97
+ "specSection": "7.2"
98
+ },
99
+ {
100
+ "name": "quotes single hyphen and hyphen-space string as object values",
101
+ "input": { "marker": "-", "note": "- item" },
102
+ "expected": "marker: \"-\"\nnote: \"- item\"",
103
+ "specSection": "7.2",
104
+ "note": "Either would otherwise read as a list item marker"
105
+ },
106
+ {
107
+ "name": "quotes single hyphen and leading-hyphen string in array",
108
+ "input": { "items": ["-", "-x"] },
109
+ "expected": "items[2]: \"-\",\"-x\"",
110
+ "specSection": "7.2"
111
+ },
112
+ {
113
+ "name": "quotes string with bracket notation",
114
+ "input": "a[test]",
115
+ "expected": "\"a[test]\"",
116
+ "specSection": "7.2"
117
+ },
118
+ {
119
+ "name": "quotes string with brace notation",
120
+ "input": "{key}",
121
+ "expected": "\"{key}\"",
122
+ "specSection": "7.2"
123
+ },
124
+ {
125
+ "name": "encodes Unicode string without quotes",
126
+ "input": "café",
127
+ "expected": "café",
128
+ "specSection": "7.2"
129
+ },
130
+ {
131
+ "name": "encodes string with emoji and spaces",
132
+ "input": "hello 👋 world",
133
+ "expected": "hello 👋 world",
134
+ "specSection": "7.2"
135
+ },
136
+ {
137
+ "name": "encodes emoji inside a quoted string",
138
+ "input": "a,🚀",
139
+ "expected": "\"a,🚀\"",
140
+ "specSection": "7.1",
141
+ "note": "Quoting is triggered by the delimiter; the supplementary scalar stays literal UTF-8, never a surrogate escape"
142
+ },
143
+ {
144
+ "name": "encodes positive integer",
145
+ "input": 42,
146
+ "expected": "42",
147
+ "specSection": "2"
148
+ },
149
+ {
150
+ "name": "encodes decimal number",
151
+ "input": 3.14,
152
+ "expected": "3.14",
153
+ "specSection": "2"
154
+ },
155
+ {
156
+ "name": "encodes negative integer",
157
+ "input": -7,
158
+ "expected": "-7",
159
+ "specSection": "2"
160
+ },
161
+ {
162
+ "name": "encodes zero",
163
+ "input": 0,
164
+ "expected": "0",
165
+ "specSection": "2"
166
+ },
167
+ {
168
+ "name": "encodes negative zero as zero",
169
+ "input": -0.0,
170
+ "expected": "0",
171
+ "specSection": "2"
172
+ },
173
+ {
174
+ "name": "encodes large integer without exponent notation",
175
+ "input": 1e6,
176
+ "expected": "1000000",
177
+ "specSection": "2",
178
+ "note": "Within the canonical decimal range"
179
+ },
180
+ {
181
+ "name": "encodes small decimal without exponent notation",
182
+ "input": 0.000001,
183
+ "expected": "0.000001",
184
+ "specSection": "2",
185
+ "note": "Lower bound of the canonical decimal range"
186
+ },
187
+ {
188
+ "name": "encodes large number",
189
+ "input": 100000000000000000000,
190
+ "expected": "100000000000000000000",
191
+ "specSection": "2"
192
+ },
193
+ {
194
+ "name": "encodes MAX_SAFE_INTEGER",
195
+ "input": 9007199254740991,
196
+ "expected": "9007199254740991",
197
+ "specSection": "2"
198
+ },
199
+ {
200
+ "name": "encodes floats with their shortest round-trip digits",
201
+ "input": [0.3333333333333333, 0.30000000000000004, -0.000001],
202
+ "expected": "[3]: 0.3333333333333333,0.30000000000000004,-0.000001",
203
+ "specSection": "2",
204
+ "minSpecVersion": "4.2"
205
+ },
206
+ {
207
+ "name": "encodes true",
208
+ "input": true,
209
+ "expected": "true",
210
+ "specSection": "2"
211
+ },
212
+ {
213
+ "name": "encodes false",
214
+ "input": false,
215
+ "expected": "false",
216
+ "specSection": "2"
217
+ },
218
+ {
219
+ "name": "encodes null",
220
+ "input": null,
221
+ "expected": "null",
222
+ "specSection": "2"
223
+ },
224
+ {
225
+ "name": "quotes leading-plus numeric-like string",
226
+ "input": "+1",
227
+ "expected": "\"+1\"",
228
+ "specSection": "7.2",
229
+ "note": "Unquoted, a v3 host-parser decoder would read the number 1"
230
+ },
231
+ {
232
+ "name": "quotes string starting with hash",
233
+ "input": "#hello",
234
+ "expected": "\"#hello\"",
235
+ "specSection": "7.2",
236
+ "note": "Comment marker at position 0 must be quoted"
237
+ },
238
+ {
239
+ "name": "quotes a root string starting with U+FEFF",
240
+ "input": "\ufeff8",
241
+ "expected": "\"\ufeff8\"",
242
+ "specSection": "7.2",
243
+ "note": "Unquoted, a decoder would remove the U+FEFF as a byte-order mark (§12) and read the number 8",
244
+ "minSpecVersion": "4.1"
245
+ },
246
+ {
247
+ "name": "encodes a large integer-valued number with its shortest round-trip digits",
248
+ "input": 123456789012345680000,
249
+ "expected": "123456789012345680000",
250
+ "specSection": "2",
251
+ "note": "The binary64 value is exactly 123456789012345683968",
252
+ "minSpecVersion": "4.2"
253
+ },
254
+ {
255
+ "name": "quotes a delimiter, colon, hyphen, or number sign that a combining mark follows",
256
+ "input": { "items": ["a,\u0301b", "-\u0301", "#\u0301"], "k": "x:\u0301" },
257
+ "expected": "items[3]: \"a,\u0301b\",\"-\u0301\",\"#\u0301\"\nk: \"x:\u0301\"",
258
+ "specSection": "1.2",
259
+ "minSpecVersion": "4.4"
260
+ }
261
+ ]
262
+ }
@@ -0,0 +1,54 @@
1
+ {
2
+ "version": "4.0",
3
+ "category": "encode",
4
+ "description": "Whitespace and formatting invariants – no trailing spaces, no trailing newlines",
5
+ "tests": [
6
+ {
7
+ "name": "maintains proper indentation for nested structures",
8
+ "input": {
9
+ "user": {
10
+ "id": 123,
11
+ "name": "Ada"
12
+ },
13
+ "items": ["a", "b"]
14
+ },
15
+ "expected": "user:\n id: 123\n name: Ada\nitems[2]: a,b",
16
+ "specSection": "12"
17
+ },
18
+ {
19
+ "name": "respects custom indentSize option",
20
+ "input": {
21
+ "user": {
22
+ "name": "Ada",
23
+ "role": "admin"
24
+ }
25
+ },
26
+ "expected": "user:\n name: Ada\n role: admin",
27
+ "specSection": "12",
28
+ "options": {
29
+ "indentSize": 4
30
+ }
31
+ },
32
+ {
33
+ "name": "leaves non-ASCII whitespace unquoted",
34
+ "input": {
35
+ "k": "\u00a0x\u00a0"
36
+ },
37
+ "expected": "k: \u00a0x\u00a0",
38
+ "specSection": "7.2",
39
+ "note": "The whitespace trigger is U+0020 and U+0009 only",
40
+ "minSpecVersion": "4.2"
41
+ },
42
+ {
43
+ "name": "indents list-item sibling fields by indentSize",
44
+ "input": {
45
+ "a": [{ "b": 1, "c": 2 }, 1]
46
+ },
47
+ "expected": "a[2]:\n - b: 1\n c: 2\n - 1",
48
+ "options": {
49
+ "indentSize": 4
50
+ },
51
+ "specSection": "10"
52
+ }
53
+ ]
54
+ }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: context_spook
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.1
4
+ version: 1.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Florian Frank
@@ -15,14 +15,14 @@ dependencies:
15
15
  requirements:
16
16
  - - ">="
17
17
  - !ruby/object:Gem::Version
18
- version: 2.17.0
18
+ version: 2.18.0
19
19
  type: :development
20
20
  prerelease: false
21
21
  version_requirements: !ruby/object:Gem::Requirement
22
22
  requirements:
23
23
  - - ">="
24
24
  - !ruby/object:Gem::Version
25
- version: 2.17.0
25
+ version: 2.18.0
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: all_images
28
28
  requirement: !ruby/object:Gem::Requirement
@@ -177,20 +177,6 @@ dependencies:
177
177
  - - "~>"
178
178
  - !ruby/object:Gem::Version
179
179
  version: '0.4'
180
- - !ruby/object:Gem::Dependency
181
- name: toon-ruby
182
- requirement: !ruby/object:Gem::Requirement
183
- requirements:
184
- - - ">="
185
- - !ruby/object:Gem::Version
186
- version: '0.1'
187
- type: :runtime
188
- prerelease: false
189
- version_requirements: !ruby/object:Gem::Requirement
190
- requirements:
191
- - - ">="
192
- - !ruby/object:Gem::Version
193
- version: '0.1'
194
180
  description: |
195
181
  context_spook is a library that collects and organizes project
196
182
  information to help AI assistants understand codebases better.
@@ -204,6 +190,7 @@ extra_rdoc_files:
204
190
  - lib/context_spook/generator.rb
205
191
  - lib/context_spook/output_context.rb
206
192
  - lib/context_spook/toon.rb
193
+ - lib/context_spook/toon/encoder.rb
207
194
  - lib/context_spook/utils.rb
208
195
  - lib/context_spook/verbose_puts.rb
209
196
  - lib/context_spook/version.rb
@@ -221,12 +208,41 @@ files:
221
208
  - lib/context_spook/generator.rb
222
209
  - lib/context_spook/output_context.rb
223
210
  - lib/context_spook/toon.rb
211
+ - lib/context_spook/toon/encoder.rb
224
212
  - lib/context_spook/toon/example.md
225
213
  - lib/context_spook/utils.rb
226
214
  - lib/context_spook/verbose_puts.rb
227
215
  - lib/context_spook/version.rb
228
216
  - spec/context_spook/generator_spec.rb
217
+ - spec/context_spook/toon_encoder_spec.rb
229
218
  - spec/context_spook/toon_spec.rb
219
+ - spec/examples/README.md
220
+ - spec/examples/conversions/keyed-tabular-objects.json
221
+ - spec/examples/conversions/keyed-tabular-objects.toon
222
+ - spec/examples/conversions/nested-field-groups.json
223
+ - spec/examples/conversions/nested-field-groups.toon
224
+ - spec/examples/conversions/tabular-arrays.json
225
+ - spec/examples/conversions/tabular-arrays.toon
226
+ - spec/examples/invalid/delimiter-mismatch.toon
227
+ - spec/examples/invalid/length-mismatch.toon
228
+ - spec/examples/invalid/multiple-root-primitives.toon
229
+ - spec/examples/valid/comments.toon
230
+ - spec/examples/valid/delimiter-scoping.toon
231
+ - spec/examples/valid/mixed-arrays.toon
232
+ - spec/examples/valid/nested-objects.toon
233
+ - spec/examples/valid/objects.toon
234
+ - spec/examples/valid/pipe-delimiter.toon
235
+ - spec/examples/valid/primitive-arrays.toon
236
+ - spec/examples/valid/tab-delimiter.toon
237
+ - spec/fixtures/encode/arrays-nested.json
238
+ - spec/fixtures/encode/arrays-objects.json
239
+ - spec/fixtures/encode/arrays-primitive.json
240
+ - spec/fixtures/encode/arrays-tabular.json
241
+ - spec/fixtures/encode/delimiters.json
242
+ - spec/fixtures/encode/objects-keyed.json
243
+ - spec/fixtures/encode/objects.json
244
+ - spec/fixtures/encode/primitives.json
245
+ - spec/fixtures/encode/whitespace.json
230
246
  - spec/spec_helper.rb
231
247
  homepage: https://github.com/flori/context_spook
232
248
  licenses:
@@ -250,10 +266,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
250
266
  - !ruby/object:Gem::Version
251
267
  version: '0'
252
268
  requirements: []
253
- rubygems_version: 4.0.3
269
+ rubygems_version: 4.0.22
254
270
  specification_version: 4
255
271
  summary: context_spook collects project context for AI
256
272
  test_files:
257
273
  - spec/context_spook/generator_spec.rb
274
+ - spec/context_spook/toon_encoder_spec.rb
258
275
  - spec/context_spook/toon_spec.rb
259
276
  - spec/spec_helper.rb