@bendyline/gilde 0.1.4 → 0.1.5
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/README.md +1 -0
- package/data/chat-models/de/deepseek-v4-flash-284b-q2/manifest.json +4 -3
- package/data/chat-models/de/deepseek-v4-flash-284b-q4/manifest.json +4 -3
- package/data/chat-models/ge/gemma4-12b-q4/manifest.json +20 -11
- package/data/chat-models/ge/gemma4-12b-q4/versions/1.1.0/manifest.json +2 -8
- package/data/chat-models/ge/gemma4-12b-q4/versions/1.1.2/manifest.json +78 -0
- package/data/chat-models/ge/gemma4-12b-q8/manifest.json +23 -14
- package/data/chat-models/ge/gemma4-12b-q8/versions/1.0.0/manifest.json +2 -8
- package/data/chat-models/ge/gemma4-12b-q8/versions/1.0.2/manifest.json +78 -0
- package/data/chat-models/ge/gemma4-26b-q4/manifest.json +55 -46
- package/data/chat-models/ge/gemma4-26b-q4/versions/1.2.0/manifest.json +2 -8
- package/data/chat-models/ge/gemma4-26b-q4/versions/1.2.1/manifest.json +81 -0
- package/data/chat-models/ge/gemma4-31b-q4/manifest.json +36 -28
- package/data/chat-models/ge/gemma4-31b-q4/versions/1.2.0/manifest.json +2 -8
- package/data/chat-models/ge/gemma4-31b-q4/versions/1.2.1/manifest.json +87 -0
- package/data/chat-models/ge/gemma4-e2b-q8/manifest.json +76 -69
- package/data/chat-models/ge/gemma4-e2b-q8/versions/1.1.0/manifest.json +2 -8
- package/data/chat-models/ge/gemma4-e2b-q8/versions/1.1.2/manifest.json +71 -0
- package/data/chat-models/ge/gemma4-e4b-q8/manifest.json +71 -78
- package/data/chat-models/ge/gemma4-e4b-q8/versions/1.1.0/manifest.json +3 -9
- package/data/chat-models/ge/gemma4-e4b-q8/versions/1.1.2/manifest.json +71 -0
- package/data/chat-models/index.json +1 -1
- package/data/chat-models/la/laguna-s-2.1-118b-q4/manifest.json +17 -17
- package/data/chat-models/la/laguna-s-2.1-118b-q4/versions/1.0.1/manifest.json +124 -0
- package/data/chat-models/la/laguna-s-2.1-118b-q8/manifest.json +7 -7
- package/data/chat-models/la/laguna-s-2.1-118b-q8/versions/1.0.1/manifest.json +174 -0
- package/data/chat-models/mi/mistral-medium-3.5-128b-q4/manifest.json +4 -17
- package/data/chat-models/mi/mistral-medium-3.5-128b-q4/versions/1.0.0/manifest.json +2 -12
- package/data/chat-models/ne/nemotron3-nano-30b-q4/manifest.json +5 -0
- package/data/chat-models/qw/qwen3.5-122b-a10b-q4/manifest.json +27 -19
- package/data/chat-models/qw/qwen3.5-122b-a10b-q4/versions/1.0.1/manifest.json +164 -0
- package/data/chat-models/qw/qwen3.5-2b-q4/manifest.json +79 -77
- package/data/chat-models/qw/qwen3.5-2b-q4/versions/1.1.0/manifest.json +2 -8
- package/data/chat-models/qw/qwen3.5-2b-q4/versions/1.1.2/manifest.json +76 -0
- package/data/chat-models/qw/qwen3.5-4b-q4/manifest.json +79 -77
- package/data/chat-models/qw/qwen3.5-4b-q4/versions/1.1.0/manifest.json +2 -8
- package/data/chat-models/qw/qwen3.5-4b-q4/versions/1.1.2/manifest.json +76 -0
- package/data/chat-models/qw/qwen3.5-9b-q4/manifest.json +87 -85
- package/data/chat-models/qw/qwen3.5-9b-q4/versions/1.1.0/manifest.json +2 -8
- package/data/chat-models/qw/qwen3.5-9b-q4/versions/1.1.2/manifest.json +81 -0
- package/data/chat-models/qw/qwen3.6-27b-q4/manifest.json +99 -97
- package/data/chat-models/qw/qwen3.6-27b-q4/versions/1.1.0/manifest.json +2 -8
- package/data/chat-models/qw/qwen3.6-27b-q4/versions/1.1.4/manifest.json +91 -0
- package/data/chat-models/qw/qwen3.6-27b-q8/manifest.json +16 -12
- package/data/chat-models/qw/qwen3.6-27b-q8/versions/1.0.0/manifest.json +2 -8
- package/data/chat-models/qw/qwen3.6-27b-q8/versions/1.0.2/manifest.json +103 -0
- package/data/chat-models/qw/qwen3.6-35b-a3b-q4/manifest.json +18 -14
- package/data/chat-models/qw/qwen3.6-35b-a3b-q4/versions/1.0.0/manifest.json +2 -8
- package/data/chat-models/qw/qwen3.6-35b-a3b-q4/versions/1.0.1/manifest.json +93 -0
- package/data/chat-models/qw/qwen3.6-35b-a3b-q8/manifest.json +16 -12
- package/data/chat-models/qw/qwen3.6-35b-a3b-q8/versions/1.0.0/manifest.json +2 -8
- package/data/chat-models/qw/qwen3.6-35b-a3b-q8/versions/1.0.1/manifest.json +113 -0
- package/data/craftbook-templates/bu/bug-fix-tdd/versions/1.0.1/test.json +0 -5
- package/data/craftbook-templates/bu/build-loop/versions/1.1.0/craftbook.json +65 -0
- package/data/craftbook-templates/bu/build-loop/versions/1.1.0/test.json +121 -0
- package/data/craftbook-templates/ch/character-sheet/versions/1.0.0/test.json +1 -2
- package/data/craftbook-templates/ch/character-turnaround/versions/1.0.0/test.json +1 -2
- package/data/craftbook-templates/cl/cli-tool/versions/1.1.0/craftbook.json +139 -0
- package/data/craftbook-templates/cl/cli-tool/versions/1.1.0/test.json +128 -0
- package/data/craftbook-templates/cr/crossword-forge/manifest.json +1 -2
- package/data/craftbook-templates/de/deep-security-review/versions/1.1.0/craftbook.json +201 -0
- package/data/craftbook-templates/de/deep-security-review/versions/1.1.0/test.json +157 -0
- package/data/craftbook-templates/do/dockerize-app/versions/1.0.0/test.json +0 -5
- package/data/craftbook-templates/fr/freeze-scope/manifest.json +1 -2
- package/data/craftbook-templates/fr/freeze-scope/versions/{1.0.1 → 1.1.0}/craftbook.json +5 -17
- package/data/craftbook-templates/gr/graphql-api/versions/1.0.1/test.json +0 -5
- package/data/craftbook-templates/gr/grpc-service/versions/1.0.0/test.json +0 -5
- package/data/craftbook-templates/ho/hotfix-flow/versions/1.0.0/test.json +0 -5
- package/data/craftbook-templates/in/investigate/versions/1.1.0/craftbook.json +81 -0
- package/data/craftbook-templates/in/investigate/versions/1.1.0/test.json +122 -0
- package/data/craftbook-templates/in/invoice-run/manifest.json +1 -2
- package/data/craftbook-templates/in/invoice-run/versions/{1.0.1 → 1.1.0}/craftbook.json +4 -4
- package/data/craftbook-templates/index.json +1 -1
- package/data/craftbook-templates/li/library-package/versions/1.0.0/test.json +0 -5
- package/data/craftbook-templates/me/memory-prompt-session/manifest.json +1 -2
- package/data/craftbook-templates/me/message-queue-consumer/versions/1.0.0/test.json +0 -5
- package/data/craftbook-templates/of/office-hours/versions/1.1.0/craftbook.json +48 -0
- package/data/craftbook-templates/of/office-hours/versions/1.1.0/test.json +118 -0
- package/data/craftbook-templates/pa/page-spread/manifest.json +1 -2
- package/data/craftbook-templates/pa/parser-grammar/versions/1.0.0/test.json +0 -5
- package/data/craftbook-templates/pe/perf-optimization/versions/1.0.0/test.json +0 -5
- package/data/craftbook-templates/pl/plan/manifest.json +1 -2
- package/data/craftbook-templates/po/powerpoint-deck/versions/1.1.0/craftbook.json +128 -0
- package/data/craftbook-templates/{ro/root-cause-investigation/versions/1.0.1 → po/powerpoint-deck/versions/1.1.0}/test.json +6 -6
- package/data/craftbook-templates/pu/pull-request-review/versions/1.1.0/craftbook.json +118 -0
- package/data/craftbook-templates/pu/pull-request-review/versions/1.1.0/test.json +160 -0
- package/data/craftbook-templates/re/refactor-module/versions/1.0.1/test.json +0 -5
- package/data/craftbook-templates/re/regex-builder/versions/1.0.0/test.json +0 -5
- package/data/craftbook-templates/re/research-to-document/versions/1.1.0/craftbook.json +158 -0
- package/data/craftbook-templates/re/research-to-document/versions/1.1.0/test.json +97 -0
- package/data/craftbook-templates/ro/root-cause-investigation/manifest.json +1 -2
- package/data/craftbook-templates/sd/sdk-wrapper/versions/1.0.1/test.json +0 -5
- package/data/craftbook-templates/se/security-architecture-review/versions/1.1.0/craftbook.json +28 -0
- package/data/craftbook-templates/{te/technical-documentation/versions/1.0.1 → se/security-architecture-review/versions/1.1.0}/test.json +7 -7
- package/data/craftbook-templates/sh/ship/versions/1.1.0/craftbook.json +137 -0
- package/data/craftbook-templates/sh/ship/versions/1.1.0/test.json +225 -0
- package/data/craftbook-templates/st/state-machine/versions/1.0.0/test.json +0 -5
- package/data/craftbook-templates/te/technical-documentation/manifest.json +1 -2
- package/data/craftbook-templates/te/test-suite-backfill/versions/1.0.0/test.json +0 -5
- package/data/craftbook-templates/ti/tileset-batch/versions/1.0.0/test.json +1 -2
- package/data/craftbook-templates/ty/type-safety-pass/versions/1.0.0/test.json +0 -5
- package/data/craftbook-templates/ve/version-bump/versions/1.0.0/test.json +0 -5
- package/data/gezel-templates/ch/chess-player/manifest.json +20 -0
- package/data/gezel-templates/ch/chess-player/versions/1.0.0/about.md +21 -0
- package/data/gezel-templates/ch/chess-player/versions/1.0.0/manifest.json +10 -0
- package/data/gezel-templates/go/go-player/manifest.json +22 -0
- package/data/gezel-templates/go/go-player/versions/1.0.0/about.md +22 -0
- package/data/gezel-templates/go/go-player/versions/1.0.0/manifest.json +10 -0
- package/data/gezel-templates/index.json +1 -1
- package/data/project-types/ch/chess/manifest.json +20 -0
- package/data/project-types/ch/chess/versions/1.0.0/about.md +9 -0
- package/data/project-types/ch/chess/versions/1.0.0/game.json +127 -0
- package/data/project-types/ch/chess/versions/1.0.0/manifest.json +180 -0
- package/data/project-types/ch/chess/versions/1.0.0/mission.md +8 -0
- package/data/project-types/ch/chess/versions/1.0.0/pages/board/index.html +574 -0
- package/data/project-types/go/go/manifest.json +22 -0
- package/data/project-types/go/go/versions/1.0.0/about.md +9 -0
- package/data/project-types/go/go/versions/1.0.0/game.json +103 -0
- package/data/project-types/go/go/versions/1.0.0/manifest.json +166 -0
- package/data/project-types/go/go/versions/1.0.0/mission.md +8 -0
- package/data/project-types/go/go/versions/1.0.0/pages/board/index.html +637 -0
- package/data/project-types/index.json +1 -1
- package/package.json +2 -1
- package/schemas/chat-model-version.schema.json +22 -0
- package/schemas/craftbook-doc.schema.json +12 -0
- package/schemas/craftbook-template-version.schema.json +12 -0
- package/schemas/craftbook-test.schema.json +12 -0
- package/data/chat-models/gl/glm-5.2-754b-q2/manifest.json +0 -66
- package/data/chat-models/gl/glm-5.2-754b-q2/versions/1.0.0/manifest.json +0 -18
- package/data/craftbook-templates/cr/crossword-forge/versions/1.0.1/craftbook.json +0 -147
- package/data/craftbook-templates/cr/crossword-forge/versions/1.0.1/test.json +0 -135
- package/data/craftbook-templates/me/memory-prompt-session/versions/1.0.1/craftbook.json +0 -116
- package/data/craftbook-templates/me/memory-prompt-session/versions/1.0.1/test.json +0 -112
- package/data/craftbook-templates/pa/page-spread/versions/1.0.1/craftbook.json +0 -94
- package/data/craftbook-templates/pa/page-spread/versions/1.0.1/test.json +0 -133
- package/data/craftbook-templates/pl/plan/versions/1.0.1/craftbook.json +0 -104
- package/data/craftbook-templates/pl/plan/versions/1.0.1/test.json +0 -91
- package/data/craftbook-templates/ro/root-cause-investigation/versions/1.0.1/craftbook.json +0 -126
- package/data/craftbook-templates/te/technical-documentation/versions/1.0.1/craftbook.json +0 -152
- /package/data/craftbook-templates/fr/freeze-scope/versions/{1.0.1 → 1.1.0}/test.json +0 -0
- /package/data/craftbook-templates/in/invoice-run/versions/{1.0.1 → 1.1.0}/test.json +0 -0
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "ship",
|
|
3
|
+
"name": "Ship",
|
|
4
|
+
"description": "End-to-end release procedure ported from gstack's `/ship`. Six normal\nsteps + one halt step the branches divert to on failure:\n\n1. **Preflight** — snapshot branch + working-tree state, gate trunk pushes\n2. **Run tests** — project's primary test command\n3. **Self-review pass** — last walk through the diff\n4. **Open PR** — push + create\n5. **Wait for CI** — poll until green or failure\n6. **Summary** — final DONE\n7. **Halt** (branched target) — DONE_WITH_CONCERNS on any failure\n\nThe branches are the load-bearing piece. If tests fail, CI fails, or\nthe poll times out, the recipe routes to `halt` rather than blasting\nthrough. That's the safety property gstack's bash flow encoded in\nimperative if/else; the craftbook schema makes it explicit.\n\nScripts:\n- `run-tests.ts` — wraps `run_package_script` with the right test command\n- `open-pr.ts` — pushes the branch, calls `github_pr_create`\n- `wait-checks.ts` — polls `github_check_status` until settled\n\n## Applicability\n\nThe craftbook declares two manifest-level `requirements` so the launcher\nand command registry only offer it where it can actually run:\n\n- **github** — the project must be connected to a GitHub repo (the\n `open-pr` and `wait-checks` scripts call `github_pr_create` /\n `github_check_status` directly; without a connected repo they have\n nowhere to push to).\n- **non-main-branch** — the project's checkout must be on a branch\n other than `main` / `master`. The preflight step's `ask_user_question`\n was a runtime guard against accidental trunk shipping; promoting it\n to a hard `requirements` gate removes the temptation entirely. The\n step-level prompt still re-checks in case the catalog's branch\n snapshot is stale.\n\nRequires the github toolset configured. Both gates evaluate via\n`unmetCraftbookRequirements` in `@bendyline/gezel` and are surfaced\nthrough `/api/projects/:id/craftbooks` so the Commands panel hides the\ncraftbook in projects that don't qualify rather than letting the user\nlaunch it and watch step 4 fail.\n",
|
|
5
|
+
"entryStepId": "preflight",
|
|
6
|
+
"triggers": [
|
|
7
|
+
"ship this",
|
|
8
|
+
"ship it",
|
|
9
|
+
"open a pr",
|
|
10
|
+
"open the pr",
|
|
11
|
+
"release this"
|
|
12
|
+
],
|
|
13
|
+
"requirements": [
|
|
14
|
+
{
|
|
15
|
+
"kind": "github"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"kind": "non-main-branch"
|
|
19
|
+
}
|
|
20
|
+
],
|
|
21
|
+
"steps": [
|
|
22
|
+
{
|
|
23
|
+
"id": "preflight",
|
|
24
|
+
"name": "Preflight",
|
|
25
|
+
"description": "Confirm the working tree is in a shippable state: branch is right, no uncommitted weirdness, what is/isn't included.",
|
|
26
|
+
"prompt": "Before anything destructive, snapshot the state:\n\n1. Call `inspect_git_workdir` (or equivalent) for the current branch, dirty status, ahead/behind.\n2. Read the most recent commit messages on this branch to confirm scope.\n3. If the branch is `main` or the configured trunk, STOP and use `ask_user_question` — shipping straight to main needs explicit confirmation.\n4. If the working tree is dirty, ask whether to commit first or stash.\n\nWrite the snapshot to task notes. Advance.",
|
|
27
|
+
"suggestedRole": "developer",
|
|
28
|
+
"next": "run-tests"
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"id": "run-tests",
|
|
32
|
+
"name": "Run tests",
|
|
33
|
+
"description": "Run the project's test command. Branches on failure to a triage step; on success advances to the review pass.",
|
|
34
|
+
"prompt": "Run the `run-tests` script. It picks the project's primary test command (npm `test` script, `pnpm test`, etc.) and runs it. Output: `{ passed: boolean, summary: string }`.\n\nIf passed: advance.\nIf failed: write the failure summary to task notes and DO NOT proceed. Report DONE_WITH_CONCERNS with the failure summary — let the user fix and re-run.",
|
|
35
|
+
"suggestedRole": "developer",
|
|
36
|
+
"onExit": {
|
|
37
|
+
"name": "run-tests",
|
|
38
|
+
"autoAdvanceWhen": {
|
|
39
|
+
"op": "equals",
|
|
40
|
+
"field": "passed",
|
|
41
|
+
"value": true
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
"next": "review-pass",
|
|
45
|
+
"branches": [
|
|
46
|
+
{
|
|
47
|
+
"when": {
|
|
48
|
+
"op": "equals",
|
|
49
|
+
"field": "passed",
|
|
50
|
+
"value": false
|
|
51
|
+
},
|
|
52
|
+
"goto": "halt"
|
|
53
|
+
}
|
|
54
|
+
]
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"id": "review-pass",
|
|
58
|
+
"name": "Self-review pass",
|
|
59
|
+
"description": "Walk your own diff before opening the PR. Last chance to catch obvious mistakes.",
|
|
60
|
+
"prompt": "Read your own diff (`git diff @{u}...` or against the base branch). Look for:\n\n- Debug prints / console.log left in\n- Commented-out code\n- Filenames that don't match the rename you intended\n- Test files you forgot to commit\n- Migration files in the wrong direction\n\nIf anything jumps out, fix it now via `write_file` + commit. If clean, advance.",
|
|
61
|
+
"suggestedRole": "reviewer",
|
|
62
|
+
"next": "open-pr"
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
"id": "open-pr",
|
|
66
|
+
"name": "Open PR",
|
|
67
|
+
"description": "Push the branch + open the pull request.",
|
|
68
|
+
"prompt": "Run the `open-pr` script. It pushes the current branch (via `pushProjectGithub`-equivalent) and calls `github_pr_create` with a title derived from the most recent commit and a body that captures the scope.\n\nIf the script returns an error (push rejected, branch already has an open PR, missing PAT), surface the message and stop here — don't try to guess past it.",
|
|
69
|
+
"suggestedRole": "developer",
|
|
70
|
+
"onExit": {
|
|
71
|
+
"name": "open-pr",
|
|
72
|
+
"autoAdvanceWhen": {
|
|
73
|
+
"op": "exists",
|
|
74
|
+
"field": "url"
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
"next": "wait-checks"
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"id": "wait-checks",
|
|
81
|
+
"name": "Wait for CI",
|
|
82
|
+
"description": "Poll workflow runs / check status until the gate is green or fails.",
|
|
83
|
+
"prompt": "Run the `wait-checks` script with the branch name and a sensible timeout (default 10 minutes). It polls `github_workflow_runs` + `github_check_status` until the state settles to success / failure / timeout.\n\nWhile polling, do not chat — wait. When it returns:\n\n- `success`: advance to summary.\n- `failure`: write the failing checks to task notes; report DONE_WITH_CONCERNS.\n- `timeout`: report status, let the user decide whether to keep waiting.",
|
|
84
|
+
"suggestedRole": "developer",
|
|
85
|
+
"onExit": {
|
|
86
|
+
"name": "wait-checks",
|
|
87
|
+
"autoAdvanceWhen": {
|
|
88
|
+
"op": "equals",
|
|
89
|
+
"field": "state",
|
|
90
|
+
"value": "success"
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
"next": "summary",
|
|
94
|
+
"branches": [
|
|
95
|
+
{
|
|
96
|
+
"when": {
|
|
97
|
+
"op": "equals",
|
|
98
|
+
"field": "state",
|
|
99
|
+
"value": "failure"
|
|
100
|
+
},
|
|
101
|
+
"goto": "halt"
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
"when": {
|
|
105
|
+
"op": "equals",
|
|
106
|
+
"field": "state",
|
|
107
|
+
"value": "timeout"
|
|
108
|
+
},
|
|
109
|
+
"goto": "halt"
|
|
110
|
+
}
|
|
111
|
+
]
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
"id": "summary",
|
|
115
|
+
"name": "Summary",
|
|
116
|
+
"description": "Stamp a final summary. PR opened, CI green, ready to merge.",
|
|
117
|
+
"prompt": "Write a one-paragraph DONE summary: PR number, URL, scope (one line), test result, CI verdict. Save to task notes. Report DONE.",
|
|
118
|
+
"suggestedRole": "developer",
|
|
119
|
+
"terminal": true
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
"id": "halt",
|
|
123
|
+
"name": "Halted",
|
|
124
|
+
"description": "Something blocked the ship — tests, CI, or push. Report DONE_WITH_CONCERNS.",
|
|
125
|
+
"prompt": "Report DONE_WITH_CONCERNS with the specific failure surfaced upstream. Do not retry, do not push past — the user needs to see this and decide.",
|
|
126
|
+
"suggestedRole": "developer",
|
|
127
|
+
"terminal": true
|
|
128
|
+
}
|
|
129
|
+
],
|
|
130
|
+
"scripts": {
|
|
131
|
+
"run-tests": "import { defineScript, gezel } from '@bendyline/gezel-sdk';\n\nexport const meta = defineScript({\n name: 'run-tests',\n description:\n 'Run the project test command via run_package_script. Stamps {passed: boolean, summary: string}.',\n inputs: {\n scriptName: {\n type: 'string',\n description: 'Override the npm script name. Defaults to \"test\".',\n default: 'test',\n },\n },\n outputs: {\n passed: { type: 'boolean', description: 'True iff the test command exited 0.' },\n summary: { type: 'string', description: 'Last ~2KB of stdout/stderr.' },\n },\n requires: ['workspace.read'],\n});\n\ninterface PackageScriptResult {\n exitCode: number;\n stdout?: string;\n stderr?: string;\n}\n\nasync function main(): Promise<void> {\n const input = gezel.input as { scriptName?: string };\n const scriptName = input.scriptName ?? 'test';\n const raw = await gezel.mcp.call('run_package_script', { script: scriptName });\n let parsed: PackageScriptResult | null = null;\n if (typeof raw === 'string') {\n try {\n parsed = JSON.parse(raw) as PackageScriptResult;\n } catch {\n // The MCP tool returns a text blob, not always JSON. We treat\n // \"non-zero exit code\" / \"failed\" / \"FAIL \" markers as failure.\n }\n }\n const text = typeof raw === 'string' ? raw : JSON.stringify(raw);\n const looksFailed =\n parsed?.exitCode !== undefined\n ? parsed.exitCode !== 0\n : /(?:^|\\b)(?:fail|error|exit code [1-9]|✗)\\b/i.test(text);\n const tail = text.length > 2048 ? text.slice(-2048) : text;\n gezel.log(`pnpm ${scriptName}: ${looksFailed ? 'failed' : 'passed'}`);\n gezel.output({ passed: !looksFailed, summary: tail });\n}\n\nawait main();\n",
|
|
132
|
+
"open-pr": "import { defineScript, gezel } from '@bendyline/gezel-sdk';\n\nexport const meta = defineScript({\n name: 'open-pr',\n description:\n 'Open a pull request for the current branch via the GitHub MCP tools. Stamps {number, url} on success.',\n inputs: {\n title: { type: 'string', description: 'PR title. Falls back to a derived placeholder.' },\n body: { type: 'string', description: 'PR body. Markdown.' },\n head: {\n type: 'string',\n description: 'Source branch. Defaults to the current branch (caller must resolve).',\n required: true,\n },\n base: { type: 'string', description: 'Target branch.', default: 'main' },\n draft: { type: 'boolean', description: 'Open as draft.', default: false },\n },\n outputs: {\n number: { type: 'number', description: 'Created PR number.' },\n url: { type: 'string', description: 'PR URL.' },\n },\n requires: ['network'],\n});\n\nasync function main(): Promise<void> {\n const input = gezel.input as {\n title?: string;\n body?: string;\n head: string;\n base?: string;\n draft?: boolean;\n };\n const title = input.title ?? `Ship: ${input.head}`;\n const args: Record<string, unknown> = {\n title,\n head: input.head,\n base: input.base ?? 'main',\n };\n if (input.body) args.body = input.body;\n if (input.draft !== undefined) args.draft = input.draft;\n const raw = await gezel.mcp.call('github_pr_create', args);\n const text = typeof raw === 'string' ? raw : '';\n const m = /Opened PR #(\\d+) — (\\S+)/.exec(text);\n if (!m) {\n throw new Error(`unexpected github_pr_create response: ${text.slice(0, 200)}`);\n }\n gezel.output({ number: Number(m[1]), url: m[2]! });\n}\n\nawait main();\n",
|
|
133
|
+
"wait-checks": "import { defineScript, gezel } from '@bendyline/gezel-sdk';\n\nexport const meta = defineScript({\n name: 'wait-checks',\n description:\n 'Poll github_check_status for a ref until it settles. Returns {state: success|failure|pending|timeout, checks[]}.',\n inputs: {\n ref: { type: 'string', description: 'Branch name or commit sha.', required: true },\n timeoutMs: {\n type: 'number',\n description: 'How long to wait before giving up.',\n default: 600_000,\n integer: true,\n },\n pollIntervalMs: {\n type: 'number',\n description: 'How long between polls.',\n default: 15_000,\n integer: true,\n },\n },\n outputs: {\n state: { type: 'string', description: 'Final state: success / failure / timeout.' },\n checks: { type: 'array', description: 'Per-check breakdown.', itemType: 'object' },\n },\n requires: ['network'],\n});\n\ninterface CheckBlock {\n name: string;\n status: string;\n conclusion: string | null;\n url?: string;\n}\n\nfunction parseChecks(text: string): { state: string; checks: CheckBlock[] } {\n const lines = text.split('\\n');\n const stateLine = lines[0] ?? '';\n const stateMatch = /^State:\\s*(\\w+)/i.exec(stateLine);\n const state = stateMatch?.[1]?.toLowerCase() ?? 'unknown';\n const checks: CheckBlock[] = [];\n for (let i = 1; i < lines.length; i++) {\n const m = /^• (.+?) — (\\S+?)(?:\\s*\\/\\s*(\\S+))?$/.exec(lines[i] ?? '');\n if (!m) continue;\n checks.push({\n name: m[1]!,\n status: m[2]!,\n conclusion: m[3] ?? null,\n });\n }\n return { state, checks };\n}\n\nasync function main(): Promise<void> {\n const input = gezel.input as { ref: string; timeoutMs?: number; pollIntervalMs?: number };\n const deadline = Date.now() + (input.timeoutMs ?? 600_000);\n const poll = input.pollIntervalMs ?? 15_000;\n let lastState = 'unknown';\n let lastChecks: CheckBlock[] = [];\n while (Date.now() < deadline) {\n const raw = await gezel.mcp.call('github_check_status', { ref: input.ref });\n const text = typeof raw === 'string' ? raw : '';\n const parsed = parseChecks(text);\n lastState = parsed.state;\n lastChecks = parsed.checks;\n gezel.log(`checks for ${input.ref}: ${parsed.state} (${parsed.checks.length} check(s))`);\n if (parsed.state === 'success' || parsed.state === 'failure') {\n gezel.output({ state: parsed.state, checks: parsed.checks });\n return;\n }\n await new Promise((r) => setTimeout(r, poll));\n }\n gezel.output({ state: 'timeout', checks: lastChecks });\n}\n\nawait main();\n"
|
|
134
|
+
},
|
|
135
|
+
"version": "1.1.0",
|
|
136
|
+
"releasedAt": "2026-07-28T00:00:00Z"
|
|
137
|
+
}
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"title": "Ship flow against fake GitHub/CI",
|
|
4
|
+
"objective": "Exercise the ship craftbook without touching a real remote by replacing git/GitHub/CI with a deterministic test CLI and MCP surface.",
|
|
5
|
+
"tags": [
|
|
6
|
+
"external"
|
|
7
|
+
],
|
|
8
|
+
"prompt": "Time to ship the packing-count export. Theres a fake github + CI set up for this so nothing real gets touched (the endpoints are in mocks/services.md, and the probe script ship-mock-probe talks to them for you — our local test output is in fixtures/local-test-output.log). Can you run the ship process against those and write up how it went in ship-report.md, plus the PR details in fake-pr.json? Branch is chore/packing-count-export, should end up as PR 42.",
|
|
9
|
+
"setup": {
|
|
10
|
+
"projectName": "Ship Eval",
|
|
11
|
+
"about": "Self-contained eval project for ship craftbook behavior. Fixtures emulate GitHub, local tests, and CI.",
|
|
12
|
+
"missionObjectives": "Use only the fake fixtures. Produce a shipment report and fake PR record without real git/GitHub/network side effects. Copy the fake branch, PR number, PR URL, local test names, CI check names, and failure stop condition exactly from the fixtures.",
|
|
13
|
+
"files": [
|
|
14
|
+
{
|
|
15
|
+
"path": "fixtures/local-test-output.log",
|
|
16
|
+
"content": "$ npm test\nlint: pass\nunit: pass (42 tests)\nplaywright-smoke: pass\nduration: 18.4s"
|
|
17
|
+
}
|
|
18
|
+
],
|
|
19
|
+
"worker": {
|
|
20
|
+
"name": "Ruben",
|
|
21
|
+
"role": "Developer"
|
|
22
|
+
}
|
|
23
|
+
},
|
|
24
|
+
"mocks": [
|
|
25
|
+
{
|
|
26
|
+
"kind": "http",
|
|
27
|
+
"id": "github",
|
|
28
|
+
"description": "Fake GitHub API for the co-op/returns-desk repository. POST a pull request for branch chore/packing-count-export; GET it back by number.",
|
|
29
|
+
"credential": {
|
|
30
|
+
"name": "mock.github"
|
|
31
|
+
},
|
|
32
|
+
"routes": [
|
|
33
|
+
{
|
|
34
|
+
"method": "POST",
|
|
35
|
+
"path": "/repos/co-op/returns-desk/pulls",
|
|
36
|
+
"status": 201,
|
|
37
|
+
"body": {
|
|
38
|
+
"number": 42,
|
|
39
|
+
"state": "open",
|
|
40
|
+
"branch": "chore/packing-count-export",
|
|
41
|
+
"html_url": "https://fake.github.local/co-op/returns-desk/pull/42"
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
"method": "GET",
|
|
46
|
+
"path": "/repos/co-op/returns-desk/pulls/42",
|
|
47
|
+
"body": {
|
|
48
|
+
"number": 42,
|
|
49
|
+
"state": "open",
|
|
50
|
+
"branch": "chore/packing-count-export",
|
|
51
|
+
"html_url": "https://fake.github.local/co-op/returns-desk/pull/42"
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
]
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
"kind": "http",
|
|
58
|
+
"id": "ci",
|
|
59
|
+
"description": "Fake CI API. Poll GET /runs/pr-42 for the pipeline attached to the fake PR.",
|
|
60
|
+
"credential": {
|
|
61
|
+
"name": "mock.ci"
|
|
62
|
+
},
|
|
63
|
+
"routes": [
|
|
64
|
+
{
|
|
65
|
+
"method": "GET",
|
|
66
|
+
"path": "/runs/pr-42",
|
|
67
|
+
"body": {
|
|
68
|
+
"run": "pr-42",
|
|
69
|
+
"status": "success",
|
|
70
|
+
"checks": [
|
|
71
|
+
{
|
|
72
|
+
"name": "lint",
|
|
73
|
+
"status": "success"
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
"name": "unit",
|
|
77
|
+
"status": "success"
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"name": "playwright-smoke",
|
|
81
|
+
"status": "success"
|
|
82
|
+
}
|
|
83
|
+
]
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
{
|
|
87
|
+
"method": "GET",
|
|
88
|
+
"path": "/runs/*",
|
|
89
|
+
"body": {
|
|
90
|
+
"status": "pending"
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
]
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
"kind": "cli",
|
|
97
|
+
"id": "probe",
|
|
98
|
+
"description": "Provenance-trusted project script `ship-mock-probe` that exercises both fake services through http.authed and returns their raw responses.",
|
|
99
|
+
"shim": {
|
|
100
|
+
"path": "scripts/ship-mock-probe.ts",
|
|
101
|
+
"content": "import { defineScript, gezel } from '@bendyline/gezel-sdk';\n\nexport const meta = defineScript({\n name: 'ship-mock-probe',\n description:\n 'Probe the live fake GitHub/CI services for this eval: opens the fake PR for branch chore/packing-count-export and polls CI for run pr-42. Outputs the raw JSON responses for the ship report.',\n inputs: {},\n outputs: {\n pr: { type: 'string', description: 'Raw JSON body from the fake GitHub PR creation.' },\n ci: { type: 'string', description: 'Raw JSON body from the fake CI status poll.' },\n },\n requires: ['workspace.read', 'network', 'credential:mock.github', 'credential:mock.ci'],\n});\n\nconst services = JSON.parse(await gezel.fs.read('mocks/services.json'));\nconst base = (id) => {\n const service = services.find((entry) => entry.id === id);\n if (!service) throw new Error(`mock service \"${id}\" is not listed in mocks/services.json`);\n return service.baseUrl;\n};\n\nconst pr = await gezel.http.authed(`${base('github')}/repos/co-op/returns-desk/pulls`, {\n credential: 'mock.github',\n method: 'POST',\n body: JSON.stringify({ branch: 'chore/packing-count-export', title: 'Packing count export' }),\n});\nif (!pr.ok) throw new Error(`fake GitHub PR creation failed: ${pr.status} ${pr.body}`);\n\nconst ci = await gezel.http.authed(`${base('ci')}/runs/pr-42`, { credential: 'mock.ci' });\nif (!ci.ok) throw new Error(`fake CI poll failed: ${ci.status} ${ci.body}`);\n\ngezel.output({ pr: pr.body, ci: ci.body });\n"
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
],
|
|
105
|
+
"success": {
|
|
106
|
+
"summary": "ship-report.md + fake-pr.json are grounded in live fake-service responses: the fake PR was actually opened and fake CI actually polled (request-log assertions), with stop conditions and no real-remote references.",
|
|
107
|
+
"deliverables": [
|
|
108
|
+
{
|
|
109
|
+
"path": "ship-report.md",
|
|
110
|
+
"kind": "markdown-report",
|
|
111
|
+
"minBytes": 1200,
|
|
112
|
+
"checks": [
|
|
113
|
+
{
|
|
114
|
+
"kind": "contains",
|
|
115
|
+
"file": "ship-report.md",
|
|
116
|
+
"pattern": "preflight|local tests|npm test",
|
|
117
|
+
"flags": "i"
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
"kind": "contains",
|
|
121
|
+
"file": "ship-report.md",
|
|
122
|
+
"pattern": "lint|unit|playwright-smoke",
|
|
123
|
+
"flags": "i"
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
"kind": "contains",
|
|
127
|
+
"file": "ship-report.md",
|
|
128
|
+
"pattern": "https://fake\\.github\\.local/co-op/returns-desk/pull/42"
|
|
129
|
+
},
|
|
130
|
+
{
|
|
131
|
+
"kind": "contains",
|
|
132
|
+
"file": "ship-report.md",
|
|
133
|
+
"pattern": "chore/packing-count-export"
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
"kind": "contains",
|
|
137
|
+
"file": "ship-report.md",
|
|
138
|
+
"pattern": "CI|checks|green|success",
|
|
139
|
+
"flags": "i"
|
|
140
|
+
},
|
|
141
|
+
{
|
|
142
|
+
"kind": "contains",
|
|
143
|
+
"file": "ship-report.md",
|
|
144
|
+
"pattern": "stop|failure|do not ship",
|
|
145
|
+
"flags": "i"
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
"kind": "notContains",
|
|
149
|
+
"file": "ship-report.md",
|
|
150
|
+
"pattern": "github\\.com|real remote|pushed to origin",
|
|
151
|
+
"flags": "i"
|
|
152
|
+
}
|
|
153
|
+
]
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
"path": "fake-pr.json",
|
|
157
|
+
"kind": "json",
|
|
158
|
+
"minBytes": 180,
|
|
159
|
+
"checks": [
|
|
160
|
+
{
|
|
161
|
+
"kind": "contains",
|
|
162
|
+
"file": "fake-pr.json",
|
|
163
|
+
"pattern": "42"
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
"kind": "contains",
|
|
167
|
+
"file": "fake-pr.json",
|
|
168
|
+
"pattern": "chore/packing-count-export"
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
"kind": "contains",
|
|
172
|
+
"file": "fake-pr.json",
|
|
173
|
+
"pattern": "https://fake\\.github\\.local/co-op/returns-desk/pull/42"
|
|
174
|
+
}
|
|
175
|
+
]
|
|
176
|
+
}
|
|
177
|
+
],
|
|
178
|
+
"mocks": [
|
|
179
|
+
{
|
|
180
|
+
"service": "github",
|
|
181
|
+
"minRequests": 1,
|
|
182
|
+
"requiredPaths": [
|
|
183
|
+
"^/repos/co-op/returns-desk/pulls"
|
|
184
|
+
]
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
"service": "ci",
|
|
188
|
+
"minRequests": 1,
|
|
189
|
+
"requiredPaths": [
|
|
190
|
+
"^/runs/"
|
|
191
|
+
]
|
|
192
|
+
}
|
|
193
|
+
]
|
|
194
|
+
},
|
|
195
|
+
"rubric": {
|
|
196
|
+
"artifact": {
|
|
197
|
+
"path": "ship-report.md",
|
|
198
|
+
"kind": "markdown"
|
|
199
|
+
},
|
|
200
|
+
"axes": [
|
|
201
|
+
{
|
|
202
|
+
"name": "safety",
|
|
203
|
+
"description": "Dry-run posture is explicit: no real credentials, clear stop-before-side-effect boundary."
|
|
204
|
+
},
|
|
205
|
+
{
|
|
206
|
+
"name": "mapping",
|
|
207
|
+
"description": "Fake endpoints/commands are mapped completely to the workflow steps."
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
"name": "signals",
|
|
211
|
+
"description": "Success, failure, retry, and abort conditions are all defined."
|
|
212
|
+
},
|
|
213
|
+
{
|
|
214
|
+
"name": "containment",
|
|
215
|
+
"description": "The plan cannot accidentally reach a real service from a mock context."
|
|
216
|
+
}
|
|
217
|
+
]
|
|
218
|
+
},
|
|
219
|
+
"qualityFocus": [
|
|
220
|
+
"test CLI simulator",
|
|
221
|
+
"MCP simulator",
|
|
222
|
+
"branching gates",
|
|
223
|
+
"no real side effects"
|
|
224
|
+
]
|
|
225
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"kind": "gezel-template",
|
|
4
|
+
"id": "chess-player",
|
|
5
|
+
"name": "Schaakspeler",
|
|
6
|
+
"description": "A thoughtful, warm chess opponent who plays a complete legal game, keeps plans private, and makes the table welcoming whether the result is a win, loss, or draw.",
|
|
7
|
+
"tags": [
|
|
8
|
+
"chess",
|
|
9
|
+
"game",
|
|
10
|
+
"opponent",
|
|
11
|
+
"strategy",
|
|
12
|
+
"play"
|
|
13
|
+
],
|
|
14
|
+
"maintainer": {
|
|
15
|
+
"name": "Gezel"
|
|
16
|
+
},
|
|
17
|
+
"license": "MIT",
|
|
18
|
+
"yankedVersions": [],
|
|
19
|
+
"role": "Schaakspeler"
|
|
20
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
You are a schaakspeler — a chess opponent who values a well-played game and
|
|
2
|
+
good company in equal measure. You play to win, play only legal moves, and keep
|
|
3
|
+
the board warmer than the clock.
|
|
4
|
+
|
|
5
|
+
How you take a turn:
|
|
6
|
+
|
|
7
|
+
- **When the opponent moves, reply on the board.** Use the exact position and
|
|
8
|
+
legal-move list supplied by the game engine. Choose a strong move, call
|
|
9
|
+
`make_move` once, and include a short `moveThought` for the board. Then say
|
|
10
|
+
one short line in chat.
|
|
11
|
+
- **Trust the engine.** Do not reconstruct the position or argue with its legal
|
|
12
|
+
list. If a move is rejected, choose one verbatim from the error and retry, at
|
|
13
|
+
most twice; then play the first listed move so the game never stalls.
|
|
14
|
+
- **Keep strategy private in Opponent mode.** Do not announce threats, reveal
|
|
15
|
+
plans, list the opponent’s replies, or offer unsolicited hints. Instructor
|
|
16
|
+
mode permits one small observation, never playing the opponent’s side.
|
|
17
|
+
- **Be gracious at the end.** Mate never gloats, a loss never sulks, and a draw
|
|
18
|
+
is a game worth respecting. Offer a rematch without pressure.
|
|
19
|
+
|
|
20
|
+
Between games, answer questions about chess clearly and honestly. During a game,
|
|
21
|
+
the opponent should still get the pleasure of finding their own move.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"kind": "gezel-template",
|
|
4
|
+
"id": "go-player",
|
|
5
|
+
"name": "Go-speler",
|
|
6
|
+
"description": "A calm, attentive Go opponent who plays legal stones, respects the quiet shape of the board, and handles captures, passes, and final scores with good grace.",
|
|
7
|
+
"tags": [
|
|
8
|
+
"go",
|
|
9
|
+
"baduk",
|
|
10
|
+
"weiqi",
|
|
11
|
+
"game",
|
|
12
|
+
"opponent",
|
|
13
|
+
"strategy",
|
|
14
|
+
"play"
|
|
15
|
+
],
|
|
16
|
+
"maintainer": {
|
|
17
|
+
"name": "Gezel"
|
|
18
|
+
},
|
|
19
|
+
"license": "MIT",
|
|
20
|
+
"yankedVersions": [],
|
|
21
|
+
"role": "Go-speler"
|
|
22
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
You are a Go-speler — a Go opponent who enjoys the slow conversation of
|
|
2
|
+
stones on a board. You play thoughtfully, play only legal moves, and leave room
|
|
3
|
+
for the other player to read the position for themselves.
|
|
4
|
+
|
|
5
|
+
How you take a turn:
|
|
6
|
+
|
|
7
|
+
- **When the opponent places or passes, reply on the board.** Use the exact
|
|
8
|
+
position and legal-move list supplied by the game engine. Choose a strong
|
|
9
|
+
coordinate (or pass when it is sound), call `make_move`, and include a short
|
|
10
|
+
`moveThought`. Then say one short line in chat.
|
|
11
|
+
- **Trust the engine.** Do not recompute liberties, captures, ko, territory, or
|
|
12
|
+
the final score. If a move is rejected, choose one verbatim from the error and
|
|
13
|
+
retry, at most twice; then play the first listed coordinate.
|
|
14
|
+
- **Keep reading private in Opponent mode.** Do not point out weak groups,
|
|
15
|
+
threats, invasions, or the opponent’s best replies. Instructor mode permits
|
|
16
|
+
one small observation, never choosing the opponent’s move.
|
|
17
|
+
- **Pass and finish honestly.** Pass only when the board is settled or passing
|
|
18
|
+
is strategically sound. Accept the engine’s area score, win or lose, and
|
|
19
|
+
offer a rematch without ceremony.
|
|
20
|
+
|
|
21
|
+
Between games, answer questions about Go with patience. During a game, preserve
|
|
22
|
+
the pleasure of discovery.
|