jev-planner 0.0.1 → 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/llms.txt ADDED
@@ -0,0 +1,206 @@
1
+ # jev-planner
2
+
3
+ > A CLI, and the library behind it, that writes a coding plan with two or more
4
+ > AIs and a judge. Each agent — Codex and Claude Code by default; DeepSeek,
5
+ > Kimi and GLM too — drafts a plan for the same task, and Jev — TypeSafe's
6
+ > typed judge — scores the drafts, orders a cross-review when one would help,
7
+ > picks the stronger plan and the agent that writes the final version, and
8
+ > decides when a plan needs no merge at all. Every agent runs read-only. Node >=
9
+ > 20.19. MIT. Ships ESM and CommonJS with type declarations.
10
+
11
+ ## Install
12
+
13
+ npm install -g jev-planner
14
+
15
+ or, without installing, `npx jev-planner "<coding task>"`. It needs each
16
+ selected agent CLI installed and logged in (`codex` and `claude` by default),
17
+ each selected chat API's key (`DEEPSEEK_API_KEY`, `MOONSHOT_API_KEY`,
18
+ `ZAI_API_KEY`), and `TYPESAFE_API_KEY` for Jev. `jev-planner doctor` checks
19
+ them; `jev-planner --help` lists every agent id.
20
+
21
+ ## Minimal working example
22
+
23
+ ```sh
24
+ jev-planner doctor
25
+ jev-planner "Add rate limiting to the public API" -o PLAN.md
26
+ jev-planner --agents claude,deepseek,glm --model glm=glm-4.6 "Add a CSV export"
27
+ jev-planner --model codex=gpt-5.6-terra --effort codex=low "Add a CSV export"
28
+ jev-planner --agents codex:sol,codex:terra --model terra=gpt-5.6-terra "Add a CSV export"
29
+ ```
30
+
31
+ The plan goes to stdout, or to the file given with `-o`; progress goes to
32
+ stderr. `--json` prints `{ plan, verdict, finalizer, selected?, debate?, timings, cost }`
33
+ instead. Every round's plans are also written as the run goes, to `round1/`,
34
+ `round2/`, …, `final/` in a new `.jev-planner/<UTC start time>/` folder in
35
+ the repository (git-ignored by its own `.gitignore`). `--rounds-dir <path>`
36
+ writes them there instead; `--no-rounds` writes none.
37
+
38
+ `--mode balanced` (the default) lets Jev skip a round the plan does not need: a
39
+ cross-review runs only while Jev rates the chance that one would materially
40
+ improve the plan at 0.65 or more, and the merge is skipped when Jev rates one
41
+ cross-reviewed plan 0.7 or more to stand alone. `--mode ultra` always runs the
42
+ first cross-review, runs a second when Jev asks, and merges unless
43
+ `--finalizer none` keeps the reviewed plan Jev rates stronger. `--mode fast` has
44
+ Jev judge each draft alone as it arrives and answers with the first it rates 0.5
45
+ or more, stopping the other agents; when it accepts none, the drafts are merged
46
+ with no cross-review. `--straggler-grace <seconds>` is how long a balanced or
47
+ fast round waits for the agents still working once half (rounded up) have
48
+ answered.
49
+
50
+ `--review-mode debate` (experimental) runs the first review as critiques and
51
+ replies: each agent lists numbered objections to every other plan, each author
52
+ accepts or rejects the ones to its own and revises it, and Jev rules on the
53
+ rejected ones in its usual call. `--claim-checks` implies it, and has agent CLIs
54
+ check the disputed claims about the repository before Jev rules.
55
+
56
+ A `jev-planner.json` in the repository (the `--cwd` folder, or the current one)
57
+ sets up every run there; `--config <path>` reads another, `--no-config` none.
58
+ Its keys follow the flags, and a flag given on the command line wins:
59
+
60
+ ```json
61
+ {
62
+ "$schema": "https://jev-planner.com/config.schema.json",
63
+ "agents": { "codex": { "model": "gpt-5.6-sol", "effort": "high" }, "claude": {} },
64
+ "mode": "ultra",
65
+ "runsDir": "planner-runs",
66
+ "task": "Add rate limiting to the public API"
67
+ }
68
+ ```
69
+
70
+ The same flow from code:
71
+
72
+ ```ts
73
+ import { PROVIDERS, Planner, TypeSafeJevJudge } from 'jev-planner'
74
+
75
+ const secrets = ['TYPESAFE_API_KEY', ...PROVIDERS.flatMap((p) => p.secretEnv)]
76
+ const agents = PROVIDERS.filter((p) => ['codex', 'deepseek'].includes(p.id)).map((p) =>
77
+ p.create({ env: process.env, omitEnv: secrets }),
78
+ )
79
+ const planner = new Planner(agents, new TypeSafeJevJudge())
80
+ const { plan, verdict, finalizer } = await planner.plan({
81
+ task: 'Add rate limiting to the public API',
82
+ cwd: process.cwd(),
83
+ timeoutMs: 600_000,
84
+ })
85
+ ```
86
+
87
+ ## API
88
+
89
+ The planner comes from `packages/core`, an internal package bundled into this one, so
90
+ everything below is imported from `jev-planner`. This package adds Jev.
91
+
92
+ | Export | Kind | What it does |
93
+ | ---------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
94
+ | `TypeSafeJevJudge` | class | A `PlanJudge` named `Jev`, backed by `@typesafe-ai/sdk`; reads `TYPESAFE_API_KEY` |
95
+ | `Planner` | class | `new Planner(agents, judge).plan(options)`: two or more agents draft, cross-review, finalize |
96
+ | `DEFAULT_STRAGGLER_GRACE_MS` | const | 90_000: what a `balanced` or `fast` round waits for a straggler before going on without it |
97
+ | `PROVIDERS` | const | Every built-in `Provider`: `codex`, `claude`, `deepseek`, `kimi`, `glm` |
98
+ | `DEFAULT_AGENTS` | const | The ids used without `--agents`: `['codex', 'claude']` |
99
+ | `cliProvider` | function | Builds a `Provider` for an agent CLI run read-only in the repository |
100
+ | `openAICompatibleProvider` | function | Builds a `Provider` for an OpenAI-compatible chat API, sent a repo snapshot |
101
+ | `runDoctor` | function | `runDoctor(cwd, providers, env?)` runs each provider's checks |
102
+ | `ProcessError` | class | Thrown when an agent CLI exits non-zero, is killed, or times out |
103
+ | `TaskValidationError` | class | Thrown by `plan` before any call when the task is empty or a placeholder |
104
+ | `Provider` | type | `{ id, label, kind, secretEnv, effort, create(setup), doctor(cwd, env) }`, one AI |
105
+ | `AgentSetup` | type | `{ name?, label?, model?, effort?, omitEnv, env, fetch? }`, what `Provider.create` is given; `name` defaults to the id |
106
+ | `CliProviderConfig` | type | `{ id, label, command, args({ model?, effort? }), effort?, events?, sessions?, auth? }`, `cliProvider`'s input |
107
+ | `OpenAICompatibleConfig` | type | `{ id, label, baseUrl, apiKeyEnv, model }`, `openAICompatibleProvider`'s input |
108
+ | `ProcessResult` | type | `{ stdout, stderr }` of a finished agent process |
109
+ | `CheckResult` | type | `{ name, ok, detail }`, one `runDoctor` check |
110
+ | `AgentName` | type | `string`: a provider id, or a name given to one (`codex:sol` is `sol`) |
111
+ | `AgentRequest` | type | `{ prompt, resumePrompt?, session?, effort?, cwd, timeoutMs, onProgress?, signal? }`, what a `PlanningAgent` is given |
112
+ | `AgentSession` | type | `{ id? }`: one agent's conversation, carried from its draft to its later calls in a run |
113
+ | `PlanningAgent` | type | `{ name, label, readsRepository?, generate(request) }`, the agent interface `Planner` drives |
114
+ | `JudgedPlan` | type | `{ agent, label, plan }`, one plan as the judge sees it |
115
+ | `PlanJudge` | type | `{ name, judge({ task, plans, stage, disputes?, model? }) }`, returns a `Verdict`; `stage` is `'solo'`, `'draft'` or `'review'`; `name` labels its stage messages |
116
+ | `Verdict` | type | Scores and confidences, the stronger plan (an agent or `tie`), the finalizer, and `disputes?` rulings |
117
+ | `PlanMode` | type | `'fast'` (the first draft the judge accepts alone), `'balanced'` (the judge skips the rounds a plan does not need) or `'ultra'` (always cross-reviews) |
118
+ | `PlanOptions` | type | `{ task, cwd, timeoutMs, mode?, maxReviewRounds?, reviewMode?, claimChecks?, stragglerGraceMs?, judgeModel?, finalizer?, selectStronger?, allowAnyTask?, resume?, reviewEfforts?, onStage?, onAgentProgress?, onRound? }` |
119
+ | `PlanResult` | type | `{ plan, verdict, finalizer, selected?, drafts, debate?, timings, cost }`; `drafts` maps agent name to its last plan |
120
+ | `PlanCost` | type | `{ mode, reviewMode, reviewRounds, synthesized, agentCalls, judgeCalls, dropped }`, what the run spent |
121
+ | `PlanRound` | type | `{ round, stage, plans, verdict?, timings, selected?, artifacts?, debate? }`, one round as `onRound` receives it |
122
+ | `ReviewMode` | type | `'standard'` (revise against every plan) or `'debate'` (critiques, replies, the judge rules on disputes; experimental) |
123
+ | `Objection` | type | `{ id, critic, target, claim, why, repo }`, one numbered objection from a critique |
124
+ | `Reply` | type | `{ id, author, decision: 'accept' \ |
125
+ | `ClaimCheck` | type | `{ checker, result: 'confirm' \ |
126
+ | `Dispute` | type | `{ id, target, critics, objections, claim, reasons, rejections, repo, check? }`, a rejected objection for the judge |
127
+ | `DisputeRuling` | type | `{ id, choice: 'critic' \ |
128
+ | `RoundDebate` | type | `{ objections, replies?, unanswered?, disputes?, overflow?, claimChecks? }`, a debate's state after a round |
129
+ | `RoundTimings` | type | `{ totalMs, agents, judgeMs? }`: one round, and each agent call and judge call in it, in ms |
130
+ | `RunTimings` | type | `{ totalMs, rounds }`: the whole run, and each round's `RoundTimings` with its `round` and `stage` |
131
+
132
+ ## Mistakes to avoid
133
+
134
+ - **Treating a run as free.** With N agents one plan is N + 1 to 3N + 1 agent
135
+ calls — `--mode ultra` spends 2N + 1, or 3N + 1 with a second review (2N or
136
+ 3N with `--finalizer none` when Jev names a stronger plan), and `--mode fast`
137
+ N or N + 1 — and one Jev call per judged round (in fast
138
+ mode, per draft judged alone), each billed to the account or key it runs
139
+ under. Run `jev-planner doctor` first rather than a real task to check the
140
+ setup.
141
+ - **Reaching for `--mode ultra` to make a plan better.** It buys every round
142
+ whether or not it changes the plan. `balanced` runs the same rounds whenever Jev
143
+ says they would help, so `ultra` mostly buys the ones it says would not.
144
+ - **Using `--mode fast` for a plan that matters.** An accepted plan is one
145
+ agent's draft that no other agent has read, and the quickest agent is judged
146
+ first. An agent it stops has still billed what it used. It rejects
147
+ `--review-mode debate` and `--claim-checks`, since it has no review.
148
+ - **Expecting `--review-mode debate` to be cheaper.** Its review is a
149
+ critique and a reply from each agent, 2N calls where a cross-review is N,
150
+ plus one per agent that checks a claim with `--claim-checks`. The checks
151
+ need two agent CLIs; with chat APIs alone they are skipped.
152
+ - **Sending a template as the task.** A placeholder — `TODO`, `<coding task>`,
153
+ `{{task}}`, text with no letters — is rejected with `TaskValidationError`
154
+ before any billed call. Pass `--allow-any-task` (`allowAnyTask: true` in the
155
+ API) only when that text really is the task.
156
+ - **Giving the task two ways.** The task comes from the arguments, from `-f`,
157
+ from the config's `task` or `taskFile`, or from stdin — passing both
158
+ arguments and `-f` is an error, and so is piping a task while the config
159
+ has one.
160
+ - **Expecting `Planner` to read `jev-planner.json`.** Only the CLI reads it;
161
+ from code, pass `PlanOptions`. A flag beats the config, and each boolean has
162
+ a `--no-` form (`--no-json`, `--no-verbose`) to turn off what it turns on.
163
+ - **Putting a key in `jev-planner.json`.** It is meant to be committed, so a
164
+ key such as `apiKey` or `token` is rejected; keys stay in the environment.
165
+ A discovered file cannot set `cwd` either: only a file passed with `--config`
166
+ can.
167
+ - **Expecting the agents to edit code.** All run read-only; the output is a
168
+ plan, not a change. The CLI itself writes only the rounds folder
169
+ (`.jev-planner/` unless `--rounds-dir` or `--no-rounds`) and `-o`'s file.
170
+ - **Expecting a chat API agent to see the whole repository.** `deepseek`,
171
+ `kimi` and `glm` get only the tracked file list and the top-level docs and
172
+ manifests; the agent CLIs read the code itself. Pair an API agent with a CLI
173
+ agent for a task that depends on code.
174
+ - **Passing `--model`, `--effort`, `--review-effort` or `--finalizer` for an
175
+ agent not in `--agents`.** All are rejected; name the agent in `--agents`
176
+ too. They take the agent's name: with `--agents codex:sol,codex:terra`,
177
+ `--model codex=…` is rejected and `--model sol=…` is right. `--effort` and `--review-effort` are for the agent CLIs only (`codex`,
178
+ `claude`); the chat APIs reject them.
179
+ - **Listing a provider twice without names.** `--agents codex,codex` is
180
+ rejected; write `codex:sol,codex:terra`. Two named agents with the same
181
+ model and effort get a warning, as their drafts may barely differ. They
182
+ share one quota and call it at once, and a rate limit (429) fails the run.
183
+ - **Hand-building two agents of one provider without names.** Pass `name` to
184
+ `Provider.create`, and keep every agent's `label` unique: the peer reviews
185
+ and Jev tell the plans apart by label.
186
+ - **Hand-building agents without `omitEnv`.** `Provider.create` needs the
187
+ variables to strip from agent subprocesses; pass every provider's
188
+ `secretEnv` and `TYPESAFE_API_KEY`, as the CLI does.
189
+ - **Being surprised by saved sessions.** Each agent CLI keeps its draft's
190
+ session and continues it in its later calls, so the review and synthesis
191
+ start with what it already read. The sessions stay in `~/.codex/sessions`
192
+ and `~/.claude/projects`, and Claude's show in its `/resume` list. Pass
193
+ `--no-resume` (`resume: false`) to keep none.
194
+ - **A short `--timeout`.** It applies to each agent call, not the whole run,
195
+ and defaults to 600 seconds; a large repository needs most of it.
196
+
197
+ ## Docs
198
+
199
+ - Documentation site: https://jev-planner.com/ — every page is also raw
200
+ markdown at the same URL plus `.md`
201
+ - Index for an agent: https://jev-planner.com/llms.txt, and
202
+ https://jev-planner.com/llms-full.txt for every page in one fetch
203
+ - README: `node_modules/jev-planner/README.md`, or
204
+ https://github.com/rxova/jev-planner/tree/main/packages/jev-planner#readme
205
+ - Package: https://www.npmjs.com/package/jev-planner
206
+ - Source: https://github.com/rxova/jev-planner
package/package.json CHANGED
@@ -1,12 +1,84 @@
1
1
  {
2
2
  "name": "jev-planner",
3
- "version": "0.0.1",
4
- "description": "Collaborative coding plans from Codex and Claude, arbitrated by TypeSafe Jev. Placeholder; first release coming soon.",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "description": "Collaborative coding plans from Codex and Claude, arbitrated by TypeSafe Jev.",
6
+ "keywords": [
7
+ "cli",
8
+ "planning",
9
+ "implementation-plan",
10
+ "codex",
11
+ "claude",
12
+ "claude-code",
13
+ "jev",
14
+ "typesafe",
15
+ "ai-agents",
16
+ "llm"
17
+ ],
5
18
  "license": "MIT",
6
19
  "author": "Jonatan Kruszewski",
20
+ "sideEffects": false,
21
+ "bin": {
22
+ "jev-planner": "./dist/bin.mjs"
23
+ },
24
+ "files": [
25
+ "dist",
26
+ "llms.txt",
27
+ "config.schema.json"
28
+ ],
29
+ "exports": {
30
+ ".": {
31
+ "import": {
32
+ "types": "./dist/index.d.mts",
33
+ "default": "./dist/index.mjs"
34
+ },
35
+ "require": {
36
+ "types": "./dist/index.d.cts",
37
+ "default": "./dist/index.cjs"
38
+ }
39
+ },
40
+ "./package.json": "./package.json"
41
+ },
42
+ "main": "./dist/index.cjs",
43
+ "module": "./dist/index.mjs",
44
+ "types": "./dist/index.d.cts",
45
+ "engines": {
46
+ "node": ">=20.19.0"
47
+ },
48
+ "dependencies": {
49
+ "@typesafe-ai/sdk": "^0.6.0"
50
+ },
51
+ "devDependencies": {
52
+ "@arethetypeswrong/cli": "^0.18.5",
53
+ "@repo/config": "0.0.0",
54
+ "@rxova/planner-core": "0.0.0",
55
+ "@types/node": "^26.6.1",
56
+ "@vitest/coverage-v8": "^5.0.1",
57
+ "publint": "^0.3.24",
58
+ "tsdown": "^0.23.0",
59
+ "tsx": "^4.23.13",
60
+ "typescript": "6.0.3",
61
+ "vitest": "^5.0.1"
62
+ },
63
+ "publishConfig": {
64
+ "access": "public"
65
+ },
7
66
  "repository": {
8
67
  "type": "git",
9
- "url": "git+https://github.com/rxova/jev-plan.git"
68
+ "url": "git+https://github.com/rxova/jev-planner.git",
69
+ "directory": "packages/jev-planner"
70
+ },
71
+ "bugs": {
72
+ "url": "https://github.com/rxova/jev-planner/issues"
10
73
  },
11
- "files": ["README.md"]
12
- }
74
+ "homepage": "https://jev-planner.com",
75
+ "scripts": {
76
+ "build": "tsdown",
77
+ "dev": "tsx src/bin.ts",
78
+ "typecheck": "tsc --noEmit",
79
+ "test": "vitest run --coverage",
80
+ "test:watch": "vitest",
81
+ "check:exports": "publint --strict && attw --pack .",
82
+ "pack:smoke": "node --import tsx ../tooling/src/pack-smoke/pack-smoke.ts"
83
+ }
84
+ }