@fungi.computer/parakeet-testing 0.0.0-stage → 0.1.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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Jamstack Consulting LLC
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,80 @@
1
- # Temporary Holding Version
1
+ # Parakeet Testing (`@fungi.computer/parakeet-testing`)
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Parakeet Testing provides shared fixtures for tests of Parakeet renderers. The
4
+ fixtures model Shiitake Session activity and one extension catalog so each
5
+ renderer can exercise the same extension and slash-completion cases.
6
+
7
+ ## Install or set up
8
+
9
+ This package provides shared test fixtures, not a runtime dependency of shipped
10
+ renderers. From the repository root, build it with:
11
+
12
+ ```sh
13
+ pnpm turbo:run run build --filter=@fungi.computer/parakeet-testing
14
+ ```
15
+
16
+ Import fixtures from `@fungi.computer/parakeet-testing` in workspace test code.
17
+
18
+ ## Quick start
19
+
20
+ This illustrative example gives a Session a running test extension slot and
21
+ checks the fixture's response to a command:
22
+
23
+ ```ts
24
+ import {
25
+ gardenCall,
26
+ gardenExtensionId,
27
+ gardenSlots,
28
+ } from "@fungi.computer/parakeet-testing";
29
+
30
+ const slots = gardenSlots();
31
+ const extension = slots[gardenExtensionId];
32
+ if (extension?.status !== "running") throw new Error("Fixture is not running");
33
+
34
+ const reply = await gardenCall("water", { bed: "fern" });
35
+ ```
36
+
37
+ The fixture test verifies slot construction and the garden reply in
38
+ [`test/garden.test.ts`](test/garden.test.ts). Renderer tests should exercise
39
+ their own Session and UI seams with these shared inputs.
40
+
41
+ ## Core concepts
42
+
43
+ `idleActivity`, `queuedActivity`, and `runningActivity` create common Session
44
+ activity states. `gardenExtensionId`, `gardenCatalog`, and `gardenSlots()`
45
+ provide a running `test-garden` extension advertising `/water`. Its `gardenCall`
46
+ function answers that command with a choice prompt when no bed is given and a
47
+ success result when one is provided.
48
+
49
+ `slashParityCases` lists composer drafts and the completion rows every renderer
50
+ should show for built-in commands plus `/water`. `slashParityFlow` describes the
51
+ shared flow: enter `/water`, choose the fern bed, and receive the success
52
+ notice.
53
+
54
+ ## API reference
55
+
56
+ See the generated [fixture API reference](docs/api/README.md) for exported
57
+ fixtures and types.
58
+
59
+ ## Examples and checks
60
+
61
+ Run the fixture contract tests with:
62
+
63
+ ```sh
64
+ pnpm --filter @fungi.computer/parakeet-testing test
65
+ ```
66
+
67
+ Consumer tests live with their renderer. This package's test verifies its
68
+ fixtures; it does not prove every renderer uses them correctly.
69
+
70
+ ## Limits and errors
71
+
72
+ These fixtures model a small extension and a fixed completion flow. They do not
73
+ provide production Session state, execute real tools, or replace tests of a
74
+ renderer's own input, completion, and dispatch behavior. The package is not
75
+ packed for publication.
76
+
77
+ ## Contribute and license
78
+
79
+ Keep shared cases deterministic and suitable for renderer tests. The package
80
+ declares an MIT license.
@@ -0,0 +1,42 @@
1
+ import type { SessionActivity, SessionExtensionSlots } from "@fungi.computer/shiitake/client";
2
+ import { type Json } from "@fungi.computer/shiitake/extensions";
3
+ import type { WhistleCatalogV1 } from "@fungi.computer/whistle/catalog";
4
+ /** Activity facts for a Session with nothing queued or running. */
5
+ export declare const idleActivity: SessionActivity;
6
+ /** Activity facts for accepted Session work awaiting its host. */
7
+ export declare function queuedActivity(commandId: string): SessionActivity;
8
+ /** Activity facts for a Session whose work is running; override what differs. */
9
+ export declare function runningActivity(overrides?: Partial<SessionActivity>): SessionActivity;
10
+ /** Activity facts for a Session with a compaction running now. */
11
+ export declare function compactingActivity(trigger?: NonNullable<SessionActivity["compaction"]>["trigger"]): SessionActivity;
12
+ /**
13
+ * A test-only extension that no client names: it advertises `/water` through
14
+ * its Session slot and answers through the ordinary extension door. Every
15
+ * Parakeet renderer proves it can offer and run it with no client change.
16
+ */
17
+ export declare const gardenExtensionId = "test-garden";
18
+ /** The catalog the garden extension advertises. */
19
+ export declare const gardenCatalog: WhistleCatalogV1;
20
+ /** The slots a Session that rosters the garden extension reports. */
21
+ export declare function gardenSlots(): SessionExtensionSlots;
22
+ /** The garden extension's door: one stateless step per call. */
23
+ export declare function gardenCall(command: string, input: Json): Promise<Json>;
24
+ /** One input every renderer must complete identically. */
25
+ export type SlashParityCase = Readonly<{
26
+ /** The composer draft. */
27
+ draft: string;
28
+ /** The row labels every renderer must show, in order. */
29
+ rows: readonly string[];
30
+ }>;
31
+ /**
32
+ * Completion cases for a runtime holding only Parakeet's built-ins and the
33
+ * garden extension. Renderers type each draft and compare the rows they draw.
34
+ */
35
+ export declare const slashParityCases: readonly SlashParityCase[];
36
+ /** The flow every renderer runs: `/water`, choose the fern bed, see the result. */
37
+ export declare const slashParityFlow: {
38
+ readonly draft: "/water";
39
+ readonly prompt: "Which bed?";
40
+ readonly choose: "Fern bed";
41
+ readonly notice: "Watered the fern bed.";
42
+ };
package/dist/index.js ADDED
@@ -0,0 +1,127 @@
1
+ import { parseExtensionJson, } from "@fungi.computer/shiitake/extensions";
2
+ import { z } from "zod";
3
+ /** Activity facts for a Session with nothing queued or running. */
4
+ export const idleActivity = {
5
+ queue: { state: "idle" },
6
+ cancellationRequested: false,
7
+ retry: null,
8
+ activeTool: null,
9
+ lastModelChoiceSequence: null,
10
+ compaction: null,
11
+ };
12
+ /** Activity facts for accepted Session work awaiting its host. */
13
+ export function queuedActivity(commandId) {
14
+ return {
15
+ ...idleActivity,
16
+ queue: { state: "queued", commandId, runningWork: null },
17
+ };
18
+ }
19
+ /** Activity facts for a Session whose work is running; override what differs. */
20
+ export function runningActivity(overrides = {}) {
21
+ return {
22
+ ...idleActivity,
23
+ queue: { state: "running", commandId: "running-command" },
24
+ ...overrides,
25
+ };
26
+ }
27
+ /** Activity facts for a Session with a compaction running now. */
28
+ export function compactingActivity(trigger = "manual") {
29
+ return runningActivity({ compaction: { trigger } });
30
+ }
31
+ /**
32
+ * A test-only extension that no client names: it advertises `/water` through
33
+ * its Session slot and answers through the ordinary extension door. Every
34
+ * Parakeet renderer proves it can offer and run it with no client change.
35
+ */
36
+ export const gardenExtensionId = "test-garden";
37
+ /** The catalog the garden extension advertises. */
38
+ export const gardenCatalog = {
39
+ protocol: "whistle.catalog/v1",
40
+ commands: [
41
+ {
42
+ id: "water",
43
+ title: "Water a garden bed",
44
+ category: "Conversation",
45
+ description: "Water one bed, or every bed at once",
46
+ projections: {
47
+ help: { order: 20 },
48
+ slash: {
49
+ aliases: ["water"],
50
+ order: 20,
51
+ arguments: {
52
+ hint: "<bed> | all",
53
+ words: [
54
+ {
55
+ word: "all",
56
+ description: "Water every bed",
57
+ arguments: { bed: "all" },
58
+ },
59
+ ],
60
+ text: { field: "bed", arguments: {} },
61
+ },
62
+ },
63
+ },
64
+ },
65
+ ],
66
+ };
67
+ /** The slots a Session that rosters the garden extension reports. */
68
+ export function gardenSlots() {
69
+ return {
70
+ [gardenExtensionId]: {
71
+ status: "running",
72
+ revision: "sha256:garden",
73
+ value: null,
74
+ catalog: parseExtensionJson(JSON.stringify(gardenCatalog)),
75
+ },
76
+ };
77
+ }
78
+ const waterInput = z.strictObject({ bed: z.string().min(1).optional() });
79
+ /** The garden extension's door: one stateless step per call. */
80
+ export function gardenCall(command, input) {
81
+ if (command !== "water")
82
+ return Promise.reject(new Error(`Unknown garden command ${command}`));
83
+ const { bed } = waterInput.parse(input);
84
+ if (bed === undefined)
85
+ return Promise.resolve({
86
+ type: "prompt",
87
+ prompt: {
88
+ type: "choice",
89
+ message: "Which bed?",
90
+ options: [
91
+ { value: "fern", label: "Fern bed" },
92
+ { value: "moss", label: "Moss bed" },
93
+ ],
94
+ },
95
+ next: { arguments: {}, answer: "bed" },
96
+ });
97
+ return Promise.resolve({
98
+ type: "done",
99
+ notice: {
100
+ type: "success",
101
+ message: bed === "all" ? "Watered every bed." : `Watered the ${bed} bed.`,
102
+ },
103
+ });
104
+ }
105
+ /**
106
+ * Completion cases for a runtime holding only Parakeet's built-ins and the
107
+ * garden extension. Renderers type each draft and compare the rows they draw.
108
+ */
109
+ export const slashParityCases = [
110
+ { draft: "/", rows: ["/help", "/water"] },
111
+ { draft: "/w", rows: ["/water"] },
112
+ { draft: "/wtr", rows: ["/water"] },
113
+ { draft: "/e", rows: ["/water"] },
114
+ { draft: "/he", rows: ["/help"] },
115
+ { draft: "/se", rows: [] },
116
+ { draft: "/water ", rows: ["all"] },
117
+ { draft: "/water a", rows: ["all"] },
118
+ { draft: "/water fern", rows: [] },
119
+ { draft: "/zzz", rows: [] },
120
+ ];
121
+ /** The flow every renderer runs: `/water`, choose the fern bed, see the result. */
122
+ export const slashParityFlow = {
123
+ draft: "/water",
124
+ prompt: "Which bed?",
125
+ choose: "Fern bed",
126
+ notice: "Watered the fern bed.",
127
+ };
@@ -0,0 +1,177 @@
1
+ <!-- Generated by Botanical API docs (TypeDoc + typedoc-plugin-markdown). Do not edit. -->
2
+
3
+ **@fungi.computer/parakeet-testing**
4
+
5
+ ---
6
+
7
+ # @fungi.computer/parakeet-testing
8
+
9
+ ## Type Aliases
10
+
11
+ ### SlashParityCase
12
+
13
+ ```ts
14
+ type SlashParityCase = Readonly<{
15
+ draft: string;
16
+ rows: readonly string[];
17
+ }>;
18
+ ```
19
+
20
+ One input every renderer must complete identically.
21
+
22
+ ## Variables
23
+
24
+ ### idleActivity
25
+
26
+ ```ts
27
+ const idleActivity: SessionActivity;
28
+ ```
29
+
30
+ Activity facts for a Session with nothing queued or running.
31
+
32
+ ---
33
+
34
+ ### gardenExtensionId
35
+
36
+ ```ts
37
+ const gardenExtensionId: "test-garden" = "test-garden";
38
+ ```
39
+
40
+ A test-only extension that no client names: it advertises `/water` through its
41
+ Session slot and answers through the ordinary extension door. Every Parakeet
42
+ renderer proves it can offer and run it with no client change.
43
+
44
+ ---
45
+
46
+ ### gardenCatalog
47
+
48
+ ```ts
49
+ const gardenCatalog: WhistleCatalogV1;
50
+ ```
51
+
52
+ The catalog the garden extension advertises.
53
+
54
+ ---
55
+
56
+ ### slashParityCases
57
+
58
+ ```ts
59
+ const slashParityCases: readonly SlashParityCase[];
60
+ ```
61
+
62
+ Completion cases for a runtime holding only Parakeet's built-ins and the garden
63
+ extension. Renderers type each draft and compare the rows they draw.
64
+
65
+ ---
66
+
67
+ ### slashParityFlow
68
+
69
+ ```ts
70
+ const slashParityFlow: object;
71
+ ```
72
+
73
+ The flow every renderer runs: `/water`, choose the fern bed, see the result.
74
+
75
+ #### Type Declaration
76
+
77
+ | Name | Type | Default value |
78
+ | ------------------------------------- | ------------------------- | ------------------------- |
79
+ | <a id="property-draft"></a> `draft` | `"/water"` | `"/water"` |
80
+ | <a id="property-prompt"></a> `prompt` | `"Which bed?"` | `"Which bed?"` |
81
+ | <a id="property-choose"></a> `choose` | `"Fern bed"` | `"Fern bed"` |
82
+ | <a id="property-notice"></a> `notice` | `"Watered the fern bed."` | `"Watered the fern bed."` |
83
+
84
+ ## Functions
85
+
86
+ ### queuedActivity()
87
+
88
+ ```ts
89
+ function queuedActivity(commandId): SessionActivity;
90
+ ```
91
+
92
+ Activity facts for accepted Session work awaiting its host.
93
+
94
+ #### Parameters
95
+
96
+ | Parameter | Type |
97
+ | ----------- | -------- |
98
+ | `commandId` | `string` |
99
+
100
+ #### Returns
101
+
102
+ `SessionActivity`
103
+
104
+ ---
105
+
106
+ ### runningActivity()
107
+
108
+ ```ts
109
+ function runningActivity(overrides?): SessionActivity;
110
+ ```
111
+
112
+ Activity facts for a Session whose work is running; override what differs.
113
+
114
+ #### Parameters
115
+
116
+ | Parameter | Type |
117
+ | ----------- | ------------------------------ |
118
+ | `overrides` | `Partial`\<`SessionActivity`\> |
119
+
120
+ #### Returns
121
+
122
+ `SessionActivity`
123
+
124
+ ---
125
+
126
+ ### compactingActivity()
127
+
128
+ ```ts
129
+ function compactingActivity(trigger?): SessionActivity;
130
+ ```
131
+
132
+ Activity facts for a Session with a compaction running now.
133
+
134
+ #### Parameters
135
+
136
+ | Parameter | Type | Default value |
137
+ | --------- | -------------------------- | ------------- |
138
+ | `trigger` | `SessionCompactionTrigger` | `"manual"` |
139
+
140
+ #### Returns
141
+
142
+ `SessionActivity`
143
+
144
+ ---
145
+
146
+ ### gardenSlots()
147
+
148
+ ```ts
149
+ function gardenSlots(): SessionExtensionSlots;
150
+ ```
151
+
152
+ The slots a Session that rosters the garden extension reports.
153
+
154
+ #### Returns
155
+
156
+ `SessionExtensionSlots`
157
+
158
+ ---
159
+
160
+ ### gardenCall()
161
+
162
+ ```ts
163
+ function gardenCall(command, input): Promise<Json>;
164
+ ```
165
+
166
+ The garden extension's door: one stateless step per call.
167
+
168
+ #### Parameters
169
+
170
+ | Parameter | Type |
171
+ | --------- | -------- |
172
+ | `command` | `string` |
173
+ | `input` | `Json` |
174
+
175
+ #### Returns
176
+
177
+ `Promise`\<`Json`\>
package/package.json CHANGED
@@ -1,6 +1,72 @@
1
1
  {
2
2
  "name": "@fungi.computer/parakeet-testing",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "0.1.0",
4
+ "author": "Levi <levi@technomancy.dev>",
5
+ "description": "Test-only garden extension and slash-parity fixtures for a typed Shiitake Session, shared by every Parakeet-protocol renderer's tests",
6
+ "type": "module",
7
+ "main": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist",
17
+ "docs/api",
18
+ "README.md",
19
+ "LICENSE"
20
+ ],
21
+ "dependencies": {
22
+ "@fungi.computer/shiitake": "0.2.0",
23
+ "@fungi.computer/whistle": "0.0.2",
24
+ "zod": "4.4.3"
25
+ },
26
+ "devDependencies": {
27
+ "@types/node": "24.13.3",
28
+ "typescript": "5.9.3",
29
+ "vitest": "4.1.11"
30
+ },
31
+ "license": "MIT",
32
+ "botanical": {
33
+ "role": "package",
34
+ "operations": {
35
+ "lint": "required",
36
+ "typecheck": "required",
37
+ "build": "required",
38
+ "test": "required",
39
+ "docs": "required",
40
+ "pack": {
41
+ "status": "not-applicable",
42
+ "reason": "Test-only fixtures for workspace renderers, like the Parakeet source it was split from; shared pack tooling not yet wired for this package"
43
+ },
44
+ "smoke": {
45
+ "status": "not-applicable",
46
+ "reason": "No runtime entry point beyond the typed fixtures its own test and consumers exercise"
47
+ },
48
+ "stranger": {
49
+ "status": "not-applicable",
50
+ "reason": "Shared stranger consumer proof not yet wired for this package, like the Parakeet source it was split from"
51
+ }
52
+ }
53
+ },
54
+ "publishConfig": {
55
+ "access": "public"
56
+ },
57
+ "repository": {
58
+ "type": "git",
59
+ "url": "git+https://github.com/fungi-computer/parakeet-testing.git"
60
+ },
61
+ "scripts": {
62
+ "lint": "eslint src test --max-warnings=0 && ../../node_modules/.bin/oxlint --config ../../oxlint.config.ts --deny-warnings src test",
63
+ "typecheck": "tsc -p tsconfig.json --noEmit",
64
+ "build": "pnpm run clean && tsc -p tsconfig.build.json",
65
+ "clean": "node --input-type=module --eval \"import { rm } from 'node:fs/promises'; await rm('dist', { recursive: true, force: true });\"",
66
+ "test": "vitest run",
67
+ "docs": "tsx ../../tooling/repository/src/docs/cli.ts check --root ../..",
68
+ "docs:write": "tsx ../../tooling/repository/src/docs/cli.ts write --root ../..",
69
+ "format:check": "node ../../tooling/repository/scripts/format-package-check.mjs",
70
+ "lint:anti-slop": "node ../../tooling/repository/scripts/lint-package-anti-slop.mjs"
71
+ }
6
72
  }