cherry-works 0.4.0 → 0.6.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/README.md +126 -29
- package/dist/cw.js +15 -17
- package/dist/main.js +64855 -4731
- package/dist/portal/main.js +49 -49
- package/dist/portal/styles.css +1 -1
- package/package.json +15 -17
package/README.md
CHANGED
|
@@ -114,20 +114,26 @@ Each kind comes up at a different time:
|
|
|
114
114
|
|---|---|
|
|
115
115
|
| `guide` | a touched file matches one of its `globs`, or on every turn when it has no globs |
|
|
116
116
|
| `sensor` | the `signal` it names is raised, and the harness runs its `run` command |
|
|
117
|
-
| `skill` | one of its `triggers` matches the request, or it is called by name as
|
|
118
|
-
| `playbook` | one of its `triggers` matches
|
|
119
|
-
| `agent` | it is spawned by
|
|
117
|
+
| `skill` | one of its `triggers` matches the request, or it is called by name as `/<id>` |
|
|
118
|
+
| `playbook` | one of its `triggers` matches, or it is called as `/<id>`; its body is a sequence of skills |
|
|
119
|
+
| `agent` | it is spawned by its id, with only the `tools` it lists |
|
|
120
120
|
| `posture` | always, wherever the host can be told what to `allow` and `deny` |
|
|
121
121
|
| `corpus` | a primitive's `rationale` cites it, to give the reasoning behind a rule |
|
|
122
122
|
| `mixin` | never on its own; its body is lent to the primitives that pull it in |
|
|
123
|
-
| `mcp` | a primitive's body names it as `
|
|
123
|
+
| `mcp` | a primitive's body names it as `[[<id>]]`: an mcp origin outside the repository, reached through `cw mcp serve` |
|
|
124
124
|
|
|
125
|
-
|
|
126
|
-
`
|
|
127
|
-
|
|
125
|
+
A skill or a playbook that is only a step of another can say
|
|
126
|
+
`disable-user-invocation: true`: it is then not offered as a `/` command, and
|
|
127
|
+
the agent still opens it when its triggers match or a playbook sends it there.
|
|
128
|
+
|
|
129
|
+
`cw kinds <kind>` gives the exact fields each kind takes. An id names exactly
|
|
130
|
+
one primitive across the whole charter, whatever its kind. If two files claim
|
|
131
|
+
the same id, the build is refused and both files are named. A primitive is
|
|
132
|
+
named by its id alone: bare in a header (`rationale: type-safety`), a test or a
|
|
133
|
+
command, and as `[[<id>]]` in a body, which the build turns into a link.
|
|
128
134
|
Every primitive is a folder holding its `index.md`, and any other file in that
|
|
129
135
|
folder is one of its assets, reached from the body as `./<file>`. An id is at
|
|
130
|
-
most 40 characters, and may be grouped with `/`: `
|
|
136
|
+
most 40 characters, and may be grouped with `/`: the mcp `mfbs/billing` is kept at
|
|
131
137
|
`.cw/charter/mcp/mfbs/billing/index.md`.
|
|
132
138
|
|
|
133
139
|
`cw build` compiles every primitive to `.cw/out/<kind>/<id>/index.md`, with its
|
|
@@ -145,16 +151,19 @@ agent reads it.
|
|
|
145
151
|
| `cw list [--kind] [--min]` | List what the charter holds |
|
|
146
152
|
| `cw kinds [kind]` | List the kinds, or the fields one of them requires |
|
|
147
153
|
| `cw add <kind> <id> [--header k=v …]` | Write a new primitive |
|
|
148
|
-
| `cw edit <
|
|
149
|
-
| `cw remove <
|
|
150
|
-
| `cw explain <
|
|
154
|
+
| `cw edit <id>` | Open a primitive's file in your editor |
|
|
155
|
+
| `cw remove <id> [--yes]` | Delete a primitive this repository authored |
|
|
156
|
+
| `cw explain <id>` | Show which file declares an id, what it pulls in and which tests name it |
|
|
151
157
|
| `cw doctor` | Check the agents, the charter, the vendor sources and the compiled output |
|
|
158
|
+
| `cw context [--exact]` | Say how many tokens the charter puts into the agent's context when a session opens |
|
|
159
|
+
| `cw sessions [--since] [--until] [--json]` | Sum up the tokens of the sessions kept on this machine, by day and by session |
|
|
152
160
|
| `cw test` | Run every case in `.cw/test/` against the charter |
|
|
161
|
+
| `cw eval` | Put every case in `.cw/eval/` to the real agent under promptfoo |
|
|
153
162
|
| `cw suite add \| edit \| remove` | Manage test files |
|
|
154
163
|
| `cw vendor add <source> [--ref] \| remove \| list` | Install, update, remove or list vendor sources |
|
|
155
164
|
| `cw portal [--port]` | Open the charter in a browser on this machine |
|
|
156
|
-
| `cw mcp auth [
|
|
157
|
-
| `cw mcp serve` | Serve every
|
|
165
|
+
| `cw mcp auth [id] [--status]` | Sign in, as yourself, to every mcp origin the charter reaches, or to one again |
|
|
166
|
+
| `cw mcp serve` | Serve every mcp origin the charter reaches to your agent, over stdio |
|
|
158
167
|
|
|
159
168
|
`cw doctor` exits with a failure status when the charter has an error, when a
|
|
160
169
|
vendored file was edited in this repository, or when the compiled output no
|
|
@@ -214,15 +223,95 @@ one:
|
|
|
214
223
|
{
|
|
215
224
|
"description": "The TypeScript guide comes up on source files.",
|
|
216
225
|
"cases": [
|
|
217
|
-
{ "do": { "touchFile": "src/one.ts" }, "expect": { "activate": "
|
|
218
|
-
{ "when": "Stop", "expect": { "run": "
|
|
226
|
+
{ "do": { "touchFile": "src/one.ts" }, "expect": { "activate": "no-any" } },
|
|
227
|
+
{ "when": "Stop", "expect": { "run": "lint" } },
|
|
219
228
|
{ "do": { "touchFile": ".env" }, "expect": { "allow": false } }
|
|
220
229
|
]
|
|
221
230
|
}
|
|
222
231
|
```
|
|
223
232
|
|
|
224
233
|
`cw test` resolves each case against the charter and reports the ones that no
|
|
225
|
-
longer hold.
|
|
234
|
+
longer hold. It runs no agent and costs nothing, so it fits in CI.
|
|
235
|
+
|
|
236
|
+
## Evaluating against the real agent
|
|
237
|
+
|
|
238
|
+
`cw test` proves what the charter says; `cw eval` proves what the agent does
|
|
239
|
+
with it. A file in `.cw/eval/` holds prompts and what is expected of each:
|
|
240
|
+
|
|
241
|
+
```json
|
|
242
|
+
{
|
|
243
|
+
"description": "Planning goes through the planning skill.",
|
|
244
|
+
"cases": [
|
|
245
|
+
{ "prompt": "plan this feature: export a report as PDF", "expect": { "invoke": "sdd-plan", "maxTokens": 200000 } },
|
|
246
|
+
{ "prompt": "add a function that totals an invoice", "expect": { "follow": "no-single-word-naming" } }
|
|
247
|
+
]
|
|
248
|
+
}
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
Each case expects at least one of:
|
|
252
|
+
|
|
253
|
+
| Expectation | Passes when |
|
|
254
|
+
|---|---|
|
|
255
|
+
| `invoke: <id>` | the agent invoked that skill or playbook |
|
|
256
|
+
| `follow: <id>` | a model judge finds the agent followed that guide |
|
|
257
|
+
| `maxTokens: <n>` | the case used no more than that many tokens |
|
|
258
|
+
|
|
259
|
+
```bash
|
|
260
|
+
cw eval
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
Every case is handed to [promptfoo](https://www.promptfoo.dev), which puts its
|
|
264
|
+
prompt to Claude Code run headless, in a worktree of your last commit with the
|
|
265
|
+
charter built, so your working tree is never touched. You never write a
|
|
266
|
+
promptfoo configuration. The first run installs promptfoo and the Claude Agent
|
|
267
|
+
SDK under `~/.cherry-works/promptfoo/`, and later runs reuse them.
|
|
268
|
+
|
|
269
|
+
The report gives each case's outcome and tokens, and the run's total. A case
|
|
270
|
+
that misses what it expects fails the run, with what the agent did instead.
|
|
271
|
+
It runs on whatever Claude Code is signed in with, or on `ANTHROPIC_API_KEY`
|
|
272
|
+
when set, and spends real tokens: commit before you run it, and keep the cases
|
|
273
|
+
few.
|
|
274
|
+
|
|
275
|
+
## What the charter costs
|
|
276
|
+
|
|
277
|
+
Everything the charter loads when a session opens — always-on guides, every
|
|
278
|
+
skill's description, every subagent's — is paid for on every turn.
|
|
279
|
+
|
|
280
|
+
```bash
|
|
281
|
+
cw context # each primitive's tokens, the largest first, estimated
|
|
282
|
+
cw context --exact # counted through the agent's own command line
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
A guide with `globs` is listed apart: it is loaded only when a file it names is
|
|
286
|
+
touched. `cw build` prints the total in one line, the portal shows the same
|
|
287
|
+
list, and `cw doctor` warns once the total passes `mainContextCeiling` in
|
|
288
|
+
`.cw/settings.json` (20,000 tokens unless you set it).
|
|
289
|
+
|
|
290
|
+
Once a session runs, the engine's own Stop hook counts what it has used, its
|
|
291
|
+
subagents included, each time the agent stops. It keeps one line per stop
|
|
292
|
+
under `~/.cherry-works/` (or the folder `sessionAnalysisFolder` names), never in
|
|
293
|
+
the repository, and tells you in one line each time a session crosses another
|
|
294
|
+
`sessionContextMark` tokens (100,000 unless you set it). The model is never
|
|
295
|
+
sent that line.
|
|
296
|
+
|
|
297
|
+
```bash
|
|
298
|
+
cw sessions # the last 31 days, by day and by session
|
|
299
|
+
cw sessions --since 2026-10-01 # 31 days from that day at most
|
|
300
|
+
cw sessions --since 2026-10-01 --until 2026-10-05 --json
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
To put a price on it, ask your agent what last week cost: the built-in
|
|
304
|
+
`cw-session-cost` skill reads the same summary, asks whether to use prices you
|
|
305
|
+
type or the provider's published ones, and answers per session and per day,
|
|
306
|
+
naming the prices it used.
|
|
307
|
+
|
|
308
|
+
```json
|
|
309
|
+
{
|
|
310
|
+
"agents": ["claude"],
|
|
311
|
+
"mainContextCeiling": 20000,
|
|
312
|
+
"sessionContextMark": 100000
|
|
313
|
+
}
|
|
314
|
+
```
|
|
226
315
|
|
|
227
316
|
## Vendor sources
|
|
228
317
|
|
|
@@ -235,7 +324,7 @@ there, test it, and push. Only its `.cw/charter/` folder is installed, under
|
|
|
235
324
|
`.cw/vendor/<name>/`, pinned to the ref you chose and committed. A repository
|
|
236
325
|
without that folder is refused, and so is one that has vendors of its own:
|
|
237
326
|
vendoring is one level deep. Vendored primitives are read-only. To differ from
|
|
238
|
-
one, write your own primitive under a new
|
|
327
|
+
one, write your own primitive under a new id.
|
|
239
328
|
|
|
240
329
|
Run `cw vendor add` again with a new `--ref` to update a source, and
|
|
241
330
|
`cw vendor remove <name>` to take it away. Run `cw build` after either.
|
|
@@ -244,12 +333,13 @@ Run `cw vendor add` again with a new `--ref` to update a source, and
|
|
|
244
333
|
|
|
245
334
|
| Charter | What it gives your agent | Install |
|
|
246
335
|
| --- | --- | --- |
|
|
336
|
+
| [sdd-charter](https://github.com/tamnguyenvt/sdd-charter) | Spec-driven development: a spec set with a status per story and a roadmap of their dependencies, and six commands (`/sdd-init`, `/sdd-plan`, `/sdd-implement`, `/sdd-bug-fix`, `/sdd-status`, `/sdd-report`) that take each story from request to merge, stopping for your yes at each step. | `cw vendor add git@github.com:tamnguyenvt/sdd-charter.git --ref v0.1.7` |
|
|
247
337
|
| [hexagonal-architecture-charter](https://github.com/tamnguyenvt/hexagonal-architecture-charter) | Sets up a hexagonal (ports and adapters) architecture in a folder you choose, then keeps the agent following it. | `cw vendor add git@github.com:tamnguyenvt/hexagonal-architecture-charter.git --ref v0.1.0` |
|
|
248
338
|
|
|
249
|
-
##
|
|
339
|
+
## MCP origins outside the repository
|
|
250
340
|
|
|
251
341
|
Much of what an agent needs to know is kept elsewhere: another service's code,
|
|
252
|
-
an issue tracker, a wiki. An `mcp` primitive declares one such
|
|
342
|
+
an issue tracker, a wiki. An `mcp` primitive declares one such mcp origin, an MCP
|
|
253
343
|
server, and the tools of it your agent may use:
|
|
254
344
|
|
|
255
345
|
```markdown
|
|
@@ -266,31 +356,38 @@ tools: ["get_file_contents", "search_code", "list_pull_requests"]
|
|
|
266
356
|
The billing service. Look here before changing anything that charges a customer.
|
|
267
357
|
```
|
|
268
358
|
|
|
269
|
-
|
|
359
|
+
An mcp origin is either an `endpoint` reached over HTTP, or a `command` with its
|
|
270
360
|
`args` that `cw` starts as a local process; a local one takes a token only, in
|
|
271
361
|
the environment variable its `tokenEnv` names. Any primitive points the agent
|
|
272
|
-
at
|
|
362
|
+
at an mcp origin by naming it in its body as `[[mfbs/billing]]`.
|
|
273
363
|
|
|
274
364
|
```bash
|
|
275
365
|
cw build # adds one entry, cw mcp serve, to your agent's .mcp.json
|
|
276
|
-
cw mcp auth # sign in to every
|
|
366
|
+
cw mcp auth # sign in to every mcp origin you are not signed in to yet
|
|
277
367
|
cw mcp auth --status
|
|
278
368
|
```
|
|
279
369
|
|
|
280
|
-
Every developer signs in as themselves, by browser where the
|
|
370
|
+
Every developer signs in as themselves, by browser where the mcp origin offers OAuth
|
|
281
371
|
or with a token typed at a hidden prompt. Credentials are kept in the operating
|
|
282
372
|
system's credential store, never in the repository, and renewed without asking
|
|
283
|
-
where the
|
|
284
|
-
given: it serves the tools each
|
|
285
|
-
your own credential.
|
|
373
|
+
where the mcp origin allows it. `cw mcp serve` is the one MCP server your agent is
|
|
374
|
+
given: it serves the tools each mcp origin declares and forwards every call under
|
|
375
|
+
your own credential. An mcp origin that is down or not signed in to loses only its own
|
|
286
376
|
tools.
|
|
287
377
|
|
|
288
|
-
|
|
289
|
-
|
|
378
|
+
The build asks each mcp origin for its tools once and keeps them beside the
|
|
379
|
+
charter, and turns your agent's own tool search on: a session opens with each
|
|
380
|
+
tool's name and no schema, and the agent looks up the one it needs. `cw mcp
|
|
381
|
+
serve` lists the kept tools without reaching any mcp origin, and reaches one
|
|
382
|
+
only for a call. A tool an `mcp` declares that its mcp origin does not list
|
|
383
|
+
stops the build.
|
|
384
|
+
|
|
385
|
+
A subagent reaches only the mcp origins it lists under `tools`: `[[<id>]]` for every
|
|
386
|
+
tool of an mcp origin, or `[[<id>]]:<tool>` for one of them.
|
|
290
387
|
|
|
291
388
|
## Your agent can write rules too
|
|
292
389
|
|
|
293
|
-
Every governed repository gets a built-in skill, `
|
|
390
|
+
Every governed repository gets a built-in skill, `cw-author`, in the
|
|
294
391
|
agent's hands from the moment `cw init` finishes. It teaches
|
|
295
392
|
the agent to ask `cw kinds` what a kind requires and to write primitives with
|
|
296
393
|
`cw add`, instead of copying fields from memory.
|
package/dist/cw.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// package.json
|
|
4
4
|
var package_default = {
|
|
5
5
|
name: "cherry-works",
|
|
6
|
-
version: "0.
|
|
6
|
+
version: "0.6.0",
|
|
7
7
|
description: "The charter engine: resolves a charter and compiles it into what a coding agent reads.",
|
|
8
8
|
keywords: [
|
|
9
9
|
"claude-code",
|
|
@@ -42,11 +42,9 @@ var package_default = {
|
|
|
42
42
|
scripts: {
|
|
43
43
|
build: "tsup && tailwindcss -i src/driver/portal/page/styles.css -o dist/portal/styles.css --minify",
|
|
44
44
|
typecheck: "tsc --noEmit && tsc --noEmit -p src/driver/portal/page",
|
|
45
|
-
test: 'pnpm run lint:deps && pnpm run build && node --import tsx --test "test/**/*.test.ts"',
|
|
46
|
-
cw: "node --import tsx main.ts",
|
|
45
|
+
test: 'pnpm run lint:deps && pnpm run build && node --import tsx --import ./scripts/moduleLoader.mjs --test "test/**/*.test.ts"',
|
|
46
|
+
cw: "node --import tsx --import ./scripts/moduleLoader.mjs main.ts",
|
|
47
47
|
"lint:deps": "depcruise src main.ts",
|
|
48
|
-
"specs:link": "node --import tsx scripts/link-specs.ts",
|
|
49
|
-
"specs:check": "node --import tsx scripts/link-specs.ts --check",
|
|
50
48
|
release: "node --import tsx scripts/release.ts",
|
|
51
49
|
prepublishOnly: `node -e "console.error('Publish with \\"pnpm release <version>\\", which checks the package first.'); process.exit(1)"`
|
|
52
50
|
},
|
|
@@ -56,6 +54,9 @@ var package_default = {
|
|
|
56
54
|
"@codemirror/language": "^6.12.4",
|
|
57
55
|
"@codemirror/state": "^6.7.4",
|
|
58
56
|
"@codemirror/view": "^6.43.11",
|
|
57
|
+
"@hono/node-server": "^2.1.1",
|
|
58
|
+
"@hono/zod-openapi": "^1.6.3",
|
|
59
|
+
"@modelcontextprotocol/sdk": "^1.31.0",
|
|
59
60
|
"@tailwindcss/cli": "^4.3.3",
|
|
60
61
|
"@tanstack/react-query": "^5.103.2",
|
|
61
62
|
"@types/node": "^22.10.2",
|
|
@@ -68,9 +69,14 @@ var package_default = {
|
|
|
68
69
|
clsx: "^2.1.1",
|
|
69
70
|
cmdk: "^1.1.1",
|
|
70
71
|
"dependency-cruiser": "^18.2.0",
|
|
72
|
+
hono: "^4.13.7",
|
|
73
|
+
"js-tiktoken": "^1.0.21",
|
|
71
74
|
"lucide-react": "^1.47.0",
|
|
72
75
|
marked: "^18.0.13",
|
|
76
|
+
picomatch: "^4.0.7",
|
|
73
77
|
playwright: "^1.63.0",
|
|
78
|
+
promptfoo: "0.123.1",
|
|
79
|
+
prompts: "^2.4.2",
|
|
74
80
|
"radix-ui": "^1.6.7",
|
|
75
81
|
react: "^19.3.0",
|
|
76
82
|
"react-dom": "^19.3.0",
|
|
@@ -80,23 +86,15 @@ var package_default = {
|
|
|
80
86
|
tsup: "^8.3.5",
|
|
81
87
|
tsx: "^4.19.2",
|
|
82
88
|
"tw-animate-css": "^1.4.0",
|
|
83
|
-
typescript: "^5.7.2"
|
|
89
|
+
typescript: "^5.7.2",
|
|
90
|
+
yaml: "^2.9.0",
|
|
91
|
+
yargs: "^18.1.0",
|
|
92
|
+
zod: "^4.6.1"
|
|
84
93
|
},
|
|
85
94
|
pnpm: {
|
|
86
95
|
onlyBuiltDependencies: [
|
|
87
96
|
"esbuild"
|
|
88
97
|
]
|
|
89
|
-
},
|
|
90
|
-
dependencies: {
|
|
91
|
-
"@hono/node-server": "^2.1.1",
|
|
92
|
-
"@hono/zod-openapi": "^1.6.3",
|
|
93
|
-
"@modelcontextprotocol/sdk": "^1.31.0",
|
|
94
|
-
hono: "^4.13.7",
|
|
95
|
-
picomatch: "^4.0.7",
|
|
96
|
-
prompts: "^2.4.2",
|
|
97
|
-
yaml: "^2.9.0",
|
|
98
|
-
yargs: "^18.1.0",
|
|
99
|
-
zod: "^4.6.1"
|
|
100
98
|
}
|
|
101
99
|
};
|
|
102
100
|
|