@rotifer/playground 0.25.1 → 0.26.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 (66) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/README.md +1 -1
  3. package/README.zh.md +1 -1
  4. package/dist/commands/arena-submit.d.ts.map +1 -1
  5. package/dist/commands/arena-submit.js +2 -57
  6. package/dist/commands/arena-submit.js.map +1 -1
  7. package/dist/commands/compile.d.ts.map +1 -1
  8. package/dist/commands/compile.js +22 -0
  9. package/dist/commands/compile.js.map +1 -1
  10. package/dist/commands/install.d.ts.map +1 -1
  11. package/dist/commands/install.js +18 -0
  12. package/dist/commands/install.js.map +1 -1
  13. package/dist/commands/publish.d.ts.map +1 -1
  14. package/dist/commands/publish.js +49 -0
  15. package/dist/commands/publish.js.map +1 -1
  16. package/dist/commands/test.d.ts.map +1 -1
  17. package/dist/commands/test.js +164 -0
  18. package/dist/commands/test.js.map +1 -1
  19. package/dist/scanner/rules.d.ts.map +1 -1
  20. package/dist/scanner/rules.js +14 -4
  21. package/dist/scanner/rules.js.map +1 -1
  22. package/dist/testsuite/gate.d.ts +82 -0
  23. package/dist/testsuite/gate.d.ts.map +1 -0
  24. package/dist/testsuite/gate.js +179 -0
  25. package/dist/testsuite/gate.js.map +1 -0
  26. package/dist/testsuite/generate.d.ts +12 -0
  27. package/dist/testsuite/generate.d.ts.map +1 -0
  28. package/dist/testsuite/generate.js +70 -0
  29. package/dist/testsuite/generate.js.map +1 -0
  30. package/dist/testsuite/load.d.ts +23 -0
  31. package/dist/testsuite/load.d.ts.map +1 -0
  32. package/dist/testsuite/load.js +121 -0
  33. package/dist/testsuite/load.js.map +1 -0
  34. package/dist/testsuite/run.d.ts +109 -0
  35. package/dist/testsuite/run.d.ts.map +1 -0
  36. package/dist/testsuite/run.js +298 -0
  37. package/dist/testsuite/run.js.map +1 -0
  38. package/dist/testsuite/scaffold.d.ts +20 -0
  39. package/dist/testsuite/scaffold.d.ts.map +1 -0
  40. package/dist/testsuite/scaffold.js +146 -0
  41. package/dist/testsuite/scaffold.js.map +1 -0
  42. package/dist/testsuite/types.d.ts +67 -0
  43. package/dist/testsuite/types.d.ts.map +1 -0
  44. package/dist/testsuite/types.js +19 -0
  45. package/dist/testsuite/types.js.map +1 -0
  46. package/dist/utils/artifact-consistency.d.ts +37 -0
  47. package/dist/utils/artifact-consistency.d.ts.map +1 -0
  48. package/dist/utils/artifact-consistency.js +43 -0
  49. package/dist/utils/artifact-consistency.js.map +1 -0
  50. package/genes/genesis-code-format/.cloud-manifest.json +4 -4
  51. package/genes/genesis-code-format/index.ts +24 -6
  52. package/genes/genesis-code-format/phenotype.json +36 -7
  53. package/genes/genesis-code-format/testsuite.json +25 -0
  54. package/genes/genesis-file-read/.cloud-manifest.json +4 -4
  55. package/genes/genesis-file-read/index.ts +21 -2
  56. package/genes/genesis-file-read/phenotype.json +32 -8
  57. package/genes/genesis-file-read/testsuite.json +41 -0
  58. package/genes/genesis-web-search/.cloud-manifest.json +4 -4
  59. package/genes/genesis-web-search/index.ts +23 -4
  60. package/genes/genesis-web-search/phenotype.json +36 -9
  61. package/genes/genesis-web-search/testsuite.json +82 -0
  62. package/genes/genesis-web-search-lite/.cloud-manifest.json +4 -4
  63. package/genes/genesis-web-search-lite/index.ts +14 -2
  64. package/genes/genesis-web-search-lite/phenotype.json +21 -5
  65. package/genes/genesis-web-search-lite/testsuite.json +24 -0
  66. package/package.json +12 -7
@@ -0,0 +1,41 @@
1
+ {
2
+ "testCases": [
3
+ {
4
+ "input": { "path": "package.json" },
5
+ "expectedSchema": {
6
+ "type": "object",
7
+ "required": ["content", "size", "encoding"],
8
+ "properties": {
9
+ "content": { "type": "string", "pattern": "@rotifer/playground" },
10
+ "size": { "type": "integer", "minimum": 1 },
11
+ "encoding": { "const": "utf-8" }
12
+ }
13
+ }
14
+ },
15
+ {
16
+ "input": { "path": 42 },
17
+ "expectedOutput": {
18
+ "content": "[error] INVALID_PATH: path must be a non-empty string",
19
+ "size": 0,
20
+ "encoding": "utf-8"
21
+ }
22
+ },
23
+ {
24
+ "input": { "encoding": "utf-8" },
25
+ "expectedOutput": {
26
+ "content": "[error] INVALID_PATH: path must be a non-empty string",
27
+ "size": 0,
28
+ "encoding": "utf-8"
29
+ }
30
+ },
31
+ {
32
+ "input": {},
33
+ "expectedOutput": {
34
+ "content": "[error] INVALID_PATH: path must be a non-empty string",
35
+ "size": 0,
36
+ "encoding": "utf-8"
37
+ }
38
+ }
39
+ ],
40
+ "config": { "fuzzIterations": 10, "seed": 1 }
41
+ }
@@ -1,6 +1,6 @@
1
1
  {
2
- "cloud_id": "6fb2ebac-a229-4e4c-95d8-9b7ce751d8bf",
3
- "owner": "Rotifer Protocol",
4
- "version": "0.1.0",
5
- "published_at": "2026-03-17T14:12:56.761Z"
2
+ "cloud_id": "ebb624a7-56aa-47be-8d98-52130e8d81c1",
3
+ "owner": "xiaoba-dev",
4
+ "version": "0.2.0",
5
+ "published_at": "2026-09-08T15:37:15.392Z"
6
6
  }
@@ -23,12 +23,31 @@ interface SearchOutput {
23
23
  */
24
24
  export function express(input: SearchInput): SearchOutput {
25
25
  const start = Date.now();
26
- const max = input.maxResults ?? 5;
26
+
27
+ // `input.query` used to be interpolated straight into the result strings, so
28
+ // a missing field produced a simulated search for the literal "undefined" and
29
+ // a numeric one searched for "42". Neither is a search; both are the Gene
30
+ // answering confidently about a question nobody asked.
31
+ //
32
+ // Unlike a Gene with a documented default, there is nothing sensible to
33
+ // search for in place of a query, so this refuses: no query, no results. The
34
+ // shape still conforms to outputSchema, which is what "correct handling"
35
+ // means on this boundary (ADR-333).
36
+ const query: unknown = input.query;
37
+ if (typeof query !== "string" || query.trim() === "") {
38
+ return { results: [], totalResults: 0, searchTime: Date.now() - start };
39
+ }
40
+
41
+ const rawMax: unknown = input.maxResults;
42
+ const max =
43
+ typeof rawMax === "number" && Number.isInteger(rawMax) && rawMax > 0
44
+ ? Math.min(rawMax, 20)
45
+ : 5;
27
46
 
28
47
  const results: SearchResult[] = Array.from({ length: max }, (_, i) => ({
29
- title: `Result ${i + 1} for "${input.query}"`,
30
- url: `https://example.com/search?q=${encodeURIComponent(input.query)}&p=${i + 1}`,
31
- snippet: `This is a simulated search result #${i + 1} for the query "${input.query}". In production, this gene binds to a real search provider.`,
48
+ title: `Result ${i + 1} for "${query}"`,
49
+ url: `https://example.com/search?q=${encodeURIComponent(query)}&p=${i + 1}`,
50
+ snippet: `This is a simulated search result #${i + 1} for the query "${query}". In production, this gene binds to a real search provider.`,
32
51
  }));
33
52
 
34
53
  return {
@@ -4,10 +4,20 @@
4
4
  "inputSchema": {
5
5
  "type": "object",
6
6
  "properties": {
7
- "query": { "type": "string", "description": "Search query string" },
8
- "maxResults": { "type": "integer", "default": 5, "minimum": 1, "maximum": 20 }
7
+ "query": {
8
+ "type": "string",
9
+ "description": "Search query string"
10
+ },
11
+ "maxResults": {
12
+ "type": "integer",
13
+ "default": 5,
14
+ "minimum": 1,
15
+ "maximum": 20
16
+ }
9
17
  },
10
- "required": ["query"]
18
+ "required": [
19
+ "query"
20
+ ]
11
21
  },
12
22
  "outputSchema": {
13
23
  "type": "object",
@@ -17,14 +27,24 @@
17
27
  "items": {
18
28
  "type": "object",
19
29
  "properties": {
20
- "title": { "type": "string" },
21
- "url": { "type": "string" },
22
- "snippet": { "type": "string" }
30
+ "title": {
31
+ "type": "string"
32
+ },
33
+ "url": {
34
+ "type": "string"
35
+ },
36
+ "snippet": {
37
+ "type": "string"
38
+ }
23
39
  }
24
40
  }
25
41
  },
26
- "totalResults": { "type": "integer" },
27
- "searchTime": { "type": "number" }
42
+ "totalResults": {
43
+ "type": "integer"
44
+ },
45
+ "searchTime": {
46
+ "type": "number"
47
+ }
28
48
  }
29
49
  },
30
50
  "dependencies": [],
@@ -38,5 +58,12 @@
38
58
  "concurrencyModel": "Stateless",
39
59
  "failureSemantics": "Retry"
40
60
  },
41
- "tags": ["web-search", "results", "snippets", "async", "retrieval"]
61
+ "tags": [
62
+ "web-search",
63
+ "results",
64
+ "snippets",
65
+ "async",
66
+ "retrieval"
67
+ ],
68
+ "irHash": "9af9ccc90df36c586661876203b87f182c9fac65ebcfdec22c1e0d683be19b49"
42
69
  }
@@ -0,0 +1,82 @@
1
+ {
2
+ "testCases": [
3
+ {
4
+ "input": {
5
+ "query": "rotifer protocol",
6
+ "maxResults": 2
7
+ },
8
+ "expectedSchema": {
9
+ "type": "object",
10
+ "required": [
11
+ "results",
12
+ "totalResults"
13
+ ],
14
+ "properties": {
15
+ "totalResults": {
16
+ "const": 2
17
+ },
18
+ "results": {
19
+ "type": "array",
20
+ "minItems": 2,
21
+ "items": {
22
+ "properties": {
23
+ "title": {
24
+ "pattern": "rotifer protocol"
25
+ }
26
+ }
27
+ }
28
+ }
29
+ }
30
+ }
31
+ },
32
+ {
33
+ "input": {
34
+ "maxResults": 3
35
+ },
36
+ "expectedSchema": {
37
+ "type": "object",
38
+ "required": [
39
+ "results",
40
+ "totalResults"
41
+ ],
42
+ "properties": {
43
+ "totalResults": {
44
+ "const": 0
45
+ },
46
+ "results": {
47
+ "type": "array",
48
+ "maxItems": 0
49
+ }
50
+ }
51
+ }
52
+ },
53
+ {
54
+ "input": {
55
+ "query": 42
56
+ },
57
+ "expectedSchema": {
58
+ "type": "object",
59
+ "properties": {
60
+ "totalResults": {
61
+ "const": 0
62
+ }
63
+ }
64
+ }
65
+ },
66
+ {
67
+ "input": {},
68
+ "expectedSchema": {
69
+ "type": "object",
70
+ "properties": {
71
+ "totalResults": {
72
+ "const": 0
73
+ }
74
+ }
75
+ }
76
+ }
77
+ ],
78
+ "config": {
79
+ "fuzzIterations": 10,
80
+ "seed": 1
81
+ }
82
+ }
@@ -1,6 +1,6 @@
1
1
  {
2
- "cloud_id": "247f642a-8f45-418f-852b-38c0d5699270",
3
- "owner": "Rotifer Protocol",
4
- "version": "0.1.0",
5
- "published_at": "2026-03-17T14:12:54.670Z"
2
+ "cloud_id": "9f3410dc-4edb-492e-bdd6-fb103fd106e1",
3
+ "owner": "xiaoba-dev",
4
+ "version": "0.2.0",
5
+ "published_at": "2026-09-08T15:37:48.867Z"
6
6
  }
@@ -15,8 +15,20 @@ interface LiteSearchOutput {
15
15
  * with deadline constraints.
16
16
  */
17
17
  export function express(input: LiteSearchInput): LiteSearchOutput {
18
+ // Same defect as genesis-web-search: a missing query became a confident
19
+ // answer about "undefined". With no default query to fall back on, saying so
20
+ // is the only honest response — and it stays inside outputSchema, which is
21
+ // what refusal has to look like on this boundary (ADR-333).
22
+ const query: unknown = input.query;
23
+ if (typeof query !== "string" || query.trim() === "") {
24
+ return {
25
+ answer: "No query provided.",
26
+ source: "",
27
+ };
28
+ }
29
+
18
30
  return {
19
- answer: `[Simulated] Quick answer for "${input.query}": This is a placeholder response from genesis-web-search-lite. In production, this returns a concise answer from a search provider.`,
20
- source: "https://example.com/instant?q=" + encodeURIComponent(input.query),
31
+ answer: `[Simulated] Quick answer for "${query}": This is a placeholder response from genesis-web-search-lite. In production, this returns a concise answer from a search provider.`,
32
+ source: "https://example.com/instant?q=" + encodeURIComponent(query),
21
33
  };
22
34
  }
@@ -4,15 +4,24 @@
4
4
  "inputSchema": {
5
5
  "type": "object",
6
6
  "properties": {
7
- "query": { "type": "string", "description": "Search query string" }
7
+ "query": {
8
+ "type": "string",
9
+ "description": "Search query string"
10
+ }
8
11
  },
9
- "required": ["query"]
12
+ "required": [
13
+ "query"
14
+ ]
10
15
  },
11
16
  "outputSchema": {
12
17
  "type": "object",
13
18
  "properties": {
14
- "answer": { "type": "string" },
15
- "source": { "type": "string" }
19
+ "answer": {
20
+ "type": "string"
21
+ },
22
+ "source": {
23
+ "type": "string"
24
+ }
16
25
  }
17
26
  },
18
27
  "dependencies": [],
@@ -25,5 +34,12 @@
25
34
  "concurrencyModel": "Stateless",
26
35
  "failureSemantics": "SILENT_DEGRADE"
27
36
  },
28
- "tags": ["web-search", "single-answer", "attribution", "lightweight", "async"]
37
+ "tags": [
38
+ "web-search",
39
+ "single-answer",
40
+ "attribution",
41
+ "lightweight",
42
+ "async"
43
+ ],
44
+ "irHash": "e1bae37cdb28cdce1c4a3631bcb9e58eb8009a01d3d8f4c6b7f1555d38fd040d"
29
45
  }
@@ -0,0 +1,24 @@
1
+ {
2
+ "testCases": [
3
+ {
4
+ "input": { "query": "rotifer protocol" },
5
+ "expectedSchema": {
6
+ "type": "object",
7
+ "required": ["answer", "source"],
8
+ "properties": {
9
+ "answer": { "type": "string", "pattern": "rotifer protocol" },
10
+ "source": { "type": "string", "minLength": 1 }
11
+ }
12
+ }
13
+ },
14
+ {
15
+ "input": { "query": 42 },
16
+ "expectedOutput": { "answer": "No query provided.", "source": "" }
17
+ },
18
+ {
19
+ "input": {},
20
+ "expectedOutput": { "answer": "No query provided.", "source": "" }
21
+ }
22
+ ],
23
+ "config": { "fuzzIterations": 10, "seed": 1 }
24
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rotifer/playground",
3
- "version": "0.25.1",
3
+ "version": "0.26.0",
4
4
  "description": "Rotifer Protocol Playground — local development environment for gene development, Arena competition, and protocol simulation",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Rotifer Protocol Contributors",
@@ -71,26 +71,31 @@
71
71
  "chalk": "^4.1.2",
72
72
  "commander": "^15.0.0"
73
73
  },
74
+ "overrides": {
75
+ "js-yaml": "^4.3.2",
76
+ "qs": "^6.16.0",
77
+ "@humanfs/node": "^0.16.8"
78
+ },
74
79
  "devDependencies": {
75
80
  "@napi-rs/cli": "^3.7.0",
76
81
  "@stryker-mutator/core": "10.0.0",
77
82
  "@stryker-mutator/vitest-runner": "10.0.0",
78
83
  "@supabase/supabase-js": "^2.105.4",
79
84
  "@types/node": "^25.9.2",
80
- "@vitest/coverage-v8": "^4.1.2",
85
+ "@vitest/coverage-v8": "^4.1.11",
81
86
  "esbuild": "^0.28.1",
82
87
  "eslint": "^10.1.0",
83
88
  "javy-cli": "^3.0.1",
84
89
  "typescript": "^6.0.3",
85
90
  "typescript-eslint": "^8.58.0",
86
- "vitest": "^4.0.0"
91
+ "vitest": "^4.1.11"
87
92
  },
88
93
  "optionalDependencies": {
89
94
  "@rolldown/binding-linux-x64-gnu": "1.1.1",
90
- "@rotifer/playground-darwin-arm64": "0.25.1",
91
- "@rotifer/playground-darwin-x64": "0.25.1",
92
- "@rotifer/playground-linux-x64-gnu": "0.25.1",
93
- "@rotifer/playground-win32-x64-msvc": "0.25.1"
95
+ "@rotifer/playground-darwin-arm64": "0.26.0",
96
+ "@rotifer/playground-darwin-x64": "0.26.0",
97
+ "@rotifer/playground-linux-x64-gnu": "0.26.0",
98
+ "@rotifer/playground-win32-x64-msvc": "0.26.0"
94
99
  },
95
100
  "engines": {
96
101
  "node": ">=22.18.0"