cherry-works 0.5.0 → 0.6.1

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 CHANGED
@@ -115,12 +115,16 @@ Each kind comes up at a different time:
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
117
  | `skill` | one of its `triggers` matches the request, or it is called by name as `/<id>` |
118
- | `playbook` | one of its `triggers` matches; its body is a sequence of skills |
118
+ | `playbook` | one of its `triggers` matches, or it is called as `/<id>`; its body is a sequence of skills |
119
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 `[[<id>]]`: a place outside the repository, reached through `cw mcp serve` |
123
+ | `mcp` | a primitive's body names it as `[[<id>]]`: an mcp origin outside the repository, reached through `cw mcp serve` |
124
+
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.
124
128
 
125
129
  `cw kinds <kind>` gives the exact fields each kind takes. An id names exactly
126
130
  one primitive across the whole charter, whatever its kind. If two files claim
@@ -151,12 +155,15 @@ agent reads it.
151
155
  | `cw remove <id> [--yes]` | Delete a primitive this repository authored |
152
156
  | `cw explain <id>` | Show which file declares an id, what it pulls in and which tests name it |
153
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 |
154
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 |
155
162
  | `cw suite add \| edit \| remove` | Manage test files |
156
163
  | `cw vendor add <source> [--ref] \| remove \| list` | Install, update, remove or list vendor sources |
157
164
  | `cw portal [--port]` | Open the charter in a browser on this machine |
158
- | `cw mcp auth [id] [--status]` | Sign in, as yourself, to every place the charter reaches, or to one again |
159
- | `cw mcp serve` | Serve every place the charter reaches to your agent, over stdio |
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 |
160
167
 
161
168
  `cw doctor` exits with a failure status when the charter has an error, when a
162
169
  vendored file was edited in this repository, or when the compiled output no
@@ -216,15 +223,95 @@ one:
216
223
  {
217
224
  "description": "The TypeScript guide comes up on source files.",
218
225
  "cases": [
219
- { "do": { "touchFile": "src/one.ts" }, "expect": { "activate": "guide:no-any" } },
220
- { "when": "Stop", "expect": { "run": "sensor:lint" } },
226
+ { "do": { "touchFile": "src/one.ts" }, "expect": { "activate": "no-any" } },
227
+ { "when": "Stop", "expect": { "run": "lint" } },
221
228
  { "do": { "touchFile": ".env" }, "expect": { "allow": false } }
222
229
  ]
223
230
  }
224
231
  ```
225
232
 
226
233
  `cw test` resolves each case against the charter and reports the ones that no
227
- 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
+ ```
228
315
 
229
316
  ## Vendor sources
230
317
 
@@ -246,13 +333,13 @@ Run `cw vendor add` again with a new `--ref` to update a source, and
246
333
 
247
334
  | Charter | What it gives your agent | Install |
248
335
  | --- | --- | --- |
249
- | [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 skills (`/sdd-init`, `/sdd-plan`, `/sdd-implement`, `/sdd-finish`, `/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.0` |
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` |
250
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` |
251
338
 
252
- ## Places outside the repository
339
+ ## MCP origins outside the repository
253
340
 
254
341
  Much of what an agent needs to know is kept elsewhere: another service's code,
255
- an issue tracker, a wiki. An `mcp` primitive declares one such place, an MCP
342
+ an issue tracker, a wiki. An `mcp` primitive declares one such mcp origin, an MCP
256
343
  server, and the tools of it your agent may use:
257
344
 
258
345
  ```markdown
@@ -269,31 +356,38 @@ tools: ["get_file_contents", "search_code", "list_pull_requests"]
269
356
  The billing service. Look here before changing anything that charges a customer.
270
357
  ```
271
358
 
272
- A place is either an `endpoint` reached over HTTP, or a `command` with its
359
+ An mcp origin is either an `endpoint` reached over HTTP, or a `command` with its
273
360
  `args` that `cw` starts as a local process; a local one takes a token only, in
274
361
  the environment variable its `tokenEnv` names. Any primitive points the agent
275
- at a place by naming it in its body as `[[mfbs/billing]]`.
362
+ at an mcp origin by naming it in its body as `[[mfbs/billing]]`.
276
363
 
277
364
  ```bash
278
365
  cw build # adds one entry, cw mcp serve, to your agent's .mcp.json
279
- cw mcp auth # sign in to every place you are not signed in to yet
366
+ cw mcp auth # sign in to every mcp origin you are not signed in to yet
280
367
  cw mcp auth --status
281
368
  ```
282
369
 
283
- Every developer signs in as themselves, by browser where the place offers OAuth
370
+ Every developer signs in as themselves, by browser where the mcp origin offers OAuth
284
371
  or with a token typed at a hidden prompt. Credentials are kept in the operating
285
372
  system's credential store, never in the repository, and renewed without asking
286
- where the place allows it. `cw mcp serve` is the one MCP server your agent is
287
- given: it serves the tools each place declares and forwards every call under
288
- your own credential. A place that is down or not signed in to loses only its own
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
289
376
  tools.
290
377
 
291
- A subagent reaches only the places it lists under `tools`: `[[<id>]]` for every
292
- tool of a place, or `[[<id>]]:<tool>` for one of them.
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.
293
387
 
294
388
  ## Your agent can write rules too
295
389
 
296
- Every governed repository gets a built-in skill, `skill:cw-author`, in the
390
+ Every governed repository gets a built-in skill, `cw-author`, in the
297
391
  agent's hands from the moment `cw init` finishes. It teaches
298
392
  the agent to ask `cw kinds` what a kind requires and to write primitives with
299
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.5.0",
6
+ version: "0.6.1",
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,8 +42,8 @@ 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
48
  release: "node --import tsx scripts/release.ts",
49
49
  prepublishOnly: `node -e "console.error('Publish with \\"pnpm release <version>\\", which checks the package first.'); process.exit(1)"`
@@ -54,6 +54,9 @@ var package_default = {
54
54
  "@codemirror/language": "^6.12.4",
55
55
  "@codemirror/state": "^6.7.4",
56
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",
57
60
  "@tailwindcss/cli": "^4.3.3",
58
61
  "@tanstack/react-query": "^5.103.2",
59
62
  "@types/node": "^22.10.2",
@@ -66,9 +69,14 @@ var package_default = {
66
69
  clsx: "^2.1.1",
67
70
  cmdk: "^1.1.1",
68
71
  "dependency-cruiser": "^18.2.0",
72
+ hono: "^4.13.7",
73
+ "js-tiktoken": "^1.0.21",
69
74
  "lucide-react": "^1.47.0",
70
75
  marked: "^18.0.13",
76
+ picomatch: "^4.0.7",
71
77
  playwright: "^1.63.0",
78
+ promptfoo: "0.123.1",
79
+ prompts: "^2.4.2",
72
80
  "radix-ui": "^1.6.7",
73
81
  react: "^19.3.0",
74
82
  "react-dom": "^19.3.0",
@@ -78,23 +86,15 @@ var package_default = {
78
86
  tsup: "^8.3.5",
79
87
  tsx: "^4.19.2",
80
88
  "tw-animate-css": "^1.4.0",
81
- typescript: "^5.7.2"
89
+ typescript: "^5.7.2",
90
+ yaml: "^2.9.0",
91
+ yargs: "^18.1.0",
92
+ zod: "^4.6.1"
82
93
  },
83
94
  pnpm: {
84
95
  onlyBuiltDependencies: [
85
96
  "esbuild"
86
97
  ]
87
- },
88
- dependencies: {
89
- "@hono/node-server": "^2.1.1",
90
- "@hono/zod-openapi": "^1.6.3",
91
- "@modelcontextprotocol/sdk": "^1.31.0",
92
- hono: "^4.13.7",
93
- picomatch: "^4.0.7",
94
- prompts: "^2.4.2",
95
- yaml: "^2.9.0",
96
- yargs: "^18.1.0",
97
- zod: "^4.6.1"
98
98
  }
99
99
  };
100
100