@webappwiz/cli 0.0.10 → 0.0.11

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/index-8xj4zxqp.js DELETED
@@ -1,343 +0,0 @@
1
- import {
2
- table
3
- } from "./index-pyjg1rtk.js";
4
- // package.json
5
- var version = "0.0.10";
6
-
7
- // skills/add.ts
8
- import { ConsoleLogger } from "webappwiz/log";
9
- import { NodeFs } from "webappwiz/system";
10
-
11
- // skills/skill.ts
12
- import { dirname } from "node:path";
13
-
14
- // templates/arbor.skill.md
15
- var arbor_skill_default = `---
16
- name: arbor
17
- description: Use the @webappwiz/arbor CLI to land your work on trunk, or a base branch given as an argument, from an isolated git worktree without pull requests. Read this before making any code change in an arbor repository, since it decides where the work happens, and whenever you need to add, claim, merge, remove, list, show, locate, or escalate a task.
18
- version: 0.0.10
19
- ---
20
-
21
- # Using arbor
22
-
23
- \`arbor\` runs many agents on one repo, each in its own git worktree, landing on
24
- trunk without pull requests. Run it with \`bunx @webappwiz/arbor <command>\` (or
25
- \`arbor\` if on PATH). \`arbor --help\` explains the commands; this file covers
26
- only what the CLI cannot tell you.
27
-
28
- **Rule:** never use raw git for state transitions arbor covers. Every landing
29
- goes through \`arbor merge\`. The only exception is finishing an in-progress
30
- rebase (\`git add\`, \`git rebase --continue\`), then merging again.
31
-
32
- A failed command prints \`{reason}\` JSON on stdout and instructions on stderr:
33
- do what stderr says. The one case to memorize is exit 4 \`lease_lost\`: stop,
34
- do not retry, another agent owns the tree.
35
-
36
- ## Before you start
37
-
38
- Other agents may already be working. Before creating anything, list the files
39
- you expect to touch, then \`arbor ls\`, and for each task in flight compare with
40
- its changed files:
41
- \`git -C "$(arbor path <task>)" diff --name-only main...task/<task>\`
42
- (\`arbor show <task>\` for its plan; neither takes its lease).
43
-
44
- If nothing overlaps, carry on. If something does, \`arbor add\` your task if you
45
- have not already and record the overlap in \`ARBOR.md\` (which task, which
46
- files). Some overlap is normal: work alongside and accept the rebase. Only
47
- when the overlap is significant and you expect merge conflicts that would be
48
- hard to resolve, \`arbor wait <task>\` on the task you overlap with instead:
49
- let it land first and your rebase is onto its work rather than against it.
50
-
51
- Waiting is caution, reserved for overlap that warrants it. Escalate
52
- instead only when the other task is doing something majorly different from
53
- yours, or contrary to it: rewriting what you are extending, or asked for the
54
- opposite of what you were. Then \`arbor escalate\` and ask the user whether to
55
- wait for it, work alongside it and accept the rebase, or drop yours.
56
-
57
- Act on how the wait ends:
58
-
59
- - \`removed\`: it landed or was dropped. Redo the overlap check (trunk moved)
60
- and carry on.
61
- - \`escalated\`: your work is blocked on a person too. Tell the human what it
62
- is blocked on and wait.
63
- - \`orphaned\`, \`stray\`, \`unrecorded\` or \`unknown\`: that tree is broken. A tree
64
- mid-merge can read as \`orphaned\` for a moment, so \`wait\` once more before
65
- believing it, then say so and ask.
66
- - exit 14 \`timeout\`, still \`working\` or \`merging\`: \`wait\` again (with
67
- \`--timeout-secs\` if the task looks close), or offer the choice of
68
- working alongside it or picking up something else, saying what you have not
69
- started.
70
-
71
- A \`stale\` lease on a \`working\` task is normal (arbor only heartbeats while a
72
- command runs): watch a task's status, never its lease.
73
-
74
- ## Workflow
75
-
76
- 1. \`arbor add <task>\`, or \`arbor claim <task>\` to resume one. When this skill
77
- is invoked with a branch argument (\`/arbor feature/auth\`), or the user
78
- names the branch the work should land on, pass it as \`--base\` to every
79
- task you create for that request. Otherwise omit \`--base\`; never guess a
80
- base from the currently checked-out branch.
81
- 2. Fill in the \`ARBOR.md\` stub \`add\` wrote at the worktree root (see below)
82
- before touching code.
83
- 3. Do the work, updating \`ARBOR.md\` as you go; commit with git (arbor never
84
- commits for you).
85
- 4. \`arbor merge\`. On failure, do what stderr says and merge again.
86
-
87
- A successful merge deletes the worktree, and your working directory with it:
88
- \`cd\` to the main tree (merge prints its path) before running anything else.
89
-
90
- ## Escalation
91
-
92
- Merge only work you verified yourself. Escalate instead when verification
93
- needs a person: external services, destructive migrations, anything tests
94
- cannot confirm. And if the user asked to see the work before it lands,
95
- escalate regardless.
96
-
97
- 1. \`arbor escalate <reason>\`.
98
- 2. Under \`## Blocked\` in \`ARBOR.md\`, state what needs verifying, ending in a
99
- question a yes/no or a sentence can answer.
100
- 3. Leave something the human can look at and print its **absolute path**
101
- (start from \`arbor path <task>\`). For anything visual or UX, that means a
102
- screenshot; if producing one is expensive or has side effects, ask before
103
- starting and say what it will cost.
104
-
105
- If you claim a tree whose \`## Blocked\` question is unanswered, do not resume
106
- or merge: ask the user and wait for the answer.
107
-
108
- ## Reporting
109
-
110
- However a task ends, say so in one block; only a merge names a base:
111
-
112
- \`\`\`markdown
113
- ### ✅ Merged \`<task>\` onto \`<base>\`
114
-
115
- One sentence blending what the task set out to do with where it ended up.
116
- \`\`\`
117
-
118
- \`\`\`markdown
119
- ### ⚠️ Escalated \`<task>\`
120
-
121
- One sentence blending what the task set out to do with what it now waits on.
122
- \`\`\`
123
-
124
- \`\`\`markdown
125
- ### 🛑 Removed \`<task>\`
126
-
127
- One sentence blending what the task set out to do with why you \`arbor rm\`ed
128
- it instead.
129
- \`\`\`
130
-
131
- Anything else worth saying goes after this block, not instead of it.
132
-
133
- ## ARBOR.md
134
-
135
- Your session can die at any moment; \`ARBOR.md\` is what lets a stranger
136
- \`arbor claim\` the task and continue. Fill in the stub \`add\` wrote to this
137
- shape:
138
-
139
- \`\`\`\`markdown
140
- # <task>
141
-
142
- ## Goal
143
-
144
- One or two lines on what done means.
145
-
146
- ## Files
147
-
148
- - every/path/you/plan/to/touch.ts
149
-
150
- ## Done
151
-
152
- - [x] finished steps move here: these checkboxes are the only progress the
153
- task reports
154
-
155
- ## Next
156
-
157
- - [ ] every step you can foresee, roughly one commit each
158
-
159
- ## Notes
160
-
161
- Decisions, dead ends, and how to verify.
162
- \`\`\`\`
163
-
164
- Keep the whole file current throughout implementation, not at the end: after
165
- each step lands, check it off and move it to \`## Done\`, and when the set of
166
- files you are touching changes, change \`## Files\` to match. A stale plan is
167
- worse than none, and a session that dies mid-task reports nothing.
168
-
169
- \`arbor show <task>\` prints the file and every way it departs from the
170
- expected shape; run it on your own task after writing the file. \`add\` excludes
171
- \`ARBOR.md\` from git for you: never commit it, and never mention it in a commit
172
- message.
173
-
174
- ## Committing
175
-
176
- Plain, human-style commit messages with **no attribution**: no
177
- \`Co-authored-by:\` trailers, no "Generated with", no agent or model names, no
178
- \`--author\` overrides. Commit as often as it helps you; a task usually takes
179
- fewer than 5 commits, and wanting many more means the task wants splitting,
180
- not squashing.
181
- `;
182
-
183
- // templates/webappwiz.skill.md
184
- var webappwiz_skill_default = `---
185
- name: webappwiz
186
- description: Check whether the webappwiz package already covers a piece of infrastructure before writing it by hand or adding a dependency for it. Read this before writing any of: time, clocks, durations or timers; logging; id generation; HTTP serving; CLI argument parsing; background tasks or queues; web workers; markdown parsing; typed event emitters; 2D geometry or spatial indexes; filesystem, env or process access; typed RPC over fetch; schema validation; AbortSignal plumbing; disposable resources; browser scroll, animation frames or visibility. Also use whenever the user says webappwiz.
187
- version: 0.0.10
188
- ---
189
-
190
- # Using webappwiz
191
-
192
- \`webappwiz\` is the parts of a web app that get written again every time, behind
193
- interfaces a test can replace. One package, one subpath per module. Before
194
- writing any of that here, find out whether it already exists there.
195
-
196
- Its README carries the whole catalogue, a table of every subpath and what it is
197
- for. Read it from \`node_modules/webappwiz/README.md\`, or, in a project that has
198
- not installed it yet, from
199
- \`https://raw.githubusercontent.com/jaredjj3/webappwiz/main/packages/webappwiz/README.md\`.
200
-
201
- Nothing in the table is close: say so in a line and write it here. Something is:
202
- read that module's own README and the exports of its \`index.ts\`, and judge
203
- against what is actually needed rather than the one-line blurb.
204
-
205
- ## It fits
206
-
207
- \`bun add webappwiz\` and import the subpath. There is no package entry point, so
208
- import \`webappwiz/time\`, never \`webappwiz\`. Fakes live under \`/testing\` beside
209
- what they replace.
210
-
211
- ## It nearly fits
212
-
213
- Do not vendor it, fork it, or patch \`node_modules\`. Write what this project
214
- needs here so nobody is blocked, leave a \`TODO: webappwiz/<subpath> once <gap>\`
215
- on it, and hand the gap over: print the block below and tell the user to give it
216
- to an agent working on the webappwiz repo.
217
-
218
- \`\`\`markdown
219
- In \`packages/webappwiz/<subpath>\`: <the gap, in a sentence>.
220
-
221
- Wanted by <this project> for <the usecase, concretely>.
222
-
223
- What is there now: <the export that comes closest, and where it stops>.
224
- What is missing: <the smallest change that closes the gap: one more method, a
225
- widened parameter, another implementation of an interface>.
226
- Called like: <the call site, written the way the caller wants to write it>.
227
- \`\`\`
228
-
229
- Describe the gap and stop. Do not design the API in the handoff: that repo has a
230
- style guide and a judge, and neither of them is here.
231
-
232
- ## It does not fit
233
-
234
- One line naming the subpath you read and why it is not the one, then write it
235
- here. A wrong module taken up is worse than one written twice.
236
-
237
- ## Rules
238
-
239
- - Never edit the webappwiz repository from this project's thread.
240
- - Never copy its source into this project.
241
- - Reading the table is the whole check, and it is cheap. Do it before adding a
242
- dependency, not after.
243
- `;
244
-
245
- // skills/skill.ts
246
- var bundled = { arbor: arbor_skill_default, webappwiz: webappwiz_skill_default };
247
- function versionOf(md) {
248
- const frontmatter = md.match(/^---\n([\s\S]*?)\n---/)?.[1] ?? "";
249
- return frontmatter.match(/^version:\s*(.+)$/m)?.[1]?.trim() ?? null;
250
- }
251
- function available(skills) {
252
- return Object.entries(skills).toSorted(([left], [right]) => left.localeCompare(right));
253
- }
254
- async function copy(name, doc, dir, opts) {
255
- const target = `${dir}/.agents/skills/${name}/SKILL.md`;
256
- await opts.fs.mkdir(dirname(target));
257
- await opts.fs.write(target, doc);
258
- opts.log.info(`wrote ${target}`);
259
- }
260
-
261
- // skills/add.ts
262
- async function add(opts) {
263
- const log = opts.log ?? new ConsoleLogger;
264
- const fs = opts.fs ?? new NodeFs;
265
- const skills = opts.skills ?? bundled;
266
- const doc = skills[opts.skill];
267
- if (doc === undefined) {
268
- const have = available(skills).map(([name]) => name);
269
- throw new Error(`no such skill: ${opts.skill} (have ${have.join(", ")})`);
270
- }
271
- await copy(opts.skill, doc, opts.dir, { log, fs });
272
- }
273
-
274
- // skills/ls.ts
275
- import { ConsoleLogger as ConsoleLogger2, color } from "webappwiz/log";
276
- import { NodeFs as NodeFs2 } from "webappwiz/system";
277
- async function ls(opts) {
278
- const log = opts.log ?? new ConsoleLogger2;
279
- const fs = opts.fs ?? new NodeFs2;
280
- const skills = opts.skills ?? bundled;
281
- const rows = [["skill", "ships", "installed"].map(color.dim)];
282
- let stale = 0;
283
- for (const [name, doc] of available(skills)) {
284
- const ships = versionOf(doc) ?? "?";
285
- const installed = await fs.read(`${opts.dir}/.agents/skills/${name}/SKILL.md`).then(versionOf).catch(() => null);
286
- if (installed !== null && installed !== ships) {
287
- stale++;
288
- }
289
- rows.push([name, ships, installed ?? "-"]);
290
- }
291
- const lines = table(rows);
292
- if (stale > 0) {
293
- lines.push("", `${stale} out of date: run \`skills update\``);
294
- }
295
- log.info(lines.join(`
296
- `));
297
- }
298
-
299
- // skills/update.ts
300
- import { ConsoleLogger as ConsoleLogger3 } from "webappwiz/log";
301
- import { NodeFs as NodeFs3 } from "webappwiz/system";
302
- async function update(opts) {
303
- const log = opts.log ?? new ConsoleLogger3;
304
- const fs = opts.fs ?? new NodeFs3;
305
- const installed = await fs.readdir(`${opts.dir}/.agents/skills`).catch(() => []);
306
- const skills = opts.skills ?? bundled;
307
- const ours = available(skills).filter(([name]) => installed.includes(name));
308
- if (ours.length === 0) {
309
- log.info(`no webappwiz skills in ${opts.dir}: add one with \`skills add\``);
310
- return;
311
- }
312
- for (const [name, doc] of ours) {
313
- await copy(name, doc, opts.dir, { log, fs });
314
- }
315
- }
316
-
317
- // update.ts
318
- import { basename } from "node:path";
319
- import { ConsoleLogger as ConsoleLogger4 } from "webappwiz/log";
320
- import { NodeFs as NodeFs4, walk } from "webappwiz/system";
321
- var DEPENDENCY = /("(?:webappwiz|@webappwiz\/[^"]+)"\s*:\s*")(?!workspace:)[^"]*(")/g;
322
- async function update2(opts) {
323
- const log = opts.log ?? new ConsoleLogger4;
324
- const fs = opts.fs ?? new NodeFs4;
325
- let count = 0;
326
- for await (const path of walk(opts.dir, { fs })) {
327
- if (basename(path) !== "package.json") {
328
- continue;
329
- }
330
- const before = await fs.read(path);
331
- const after = before.replace(DEPENDENCY, `$1${opts.version}$2`);
332
- if (after === before) {
333
- continue;
334
- }
335
- await fs.write(path, after);
336
- log.info(`updated ${path}`);
337
- count++;
338
- }
339
- log.info(`${count} package.json pinned to ${opts.version}`);
340
- await update({ dir: opts.dir, log, fs, skills: opts.skills });
341
- }
342
-
343
- export { version, add, ls, update, update2 as update1 };
package/index-htwb54c6.js DELETED
@@ -1,44 +0,0 @@
1
- // rules.ts
2
- import { defineRules } from "@webappwiz/rules";
3
- import {
4
- ClassesOverFunctionExports,
5
- CommentsSayWhyNotWhat,
6
- DevServersFindAPort,
7
- DocCommentsAddressUsers,
8
- ExportLeadsTheFile,
9
- FakesOverMocks,
10
- MatchersOverTestLogic,
11
- NamedOptionsLast,
12
- NoEmDashes,
13
- ObjectsOverCallbacks,
14
- OneClassPerFile,
15
- OneDirPerInterface,
16
- ParametersDeclareFields,
17
- ReactiveOverUseState,
18
- ResourcesAreDisposable,
19
- SimpleTestSetup,
20
- TestsOwnTheirState
21
- } from "@webappwiz/rules/catalog";
22
- var JUDGE_RULES = defineRules({
23
- rules: [
24
- new NoEmDashes,
25
- new OneClassPerFile,
26
- new ExportLeadsTheFile,
27
- new ParametersDeclareFields,
28
- new ClassesOverFunctionExports,
29
- new ObjectsOverCallbacks,
30
- new NamedOptionsLast,
31
- new SimpleTestSetup,
32
- new TestsOwnTheirState,
33
- new FakesOverMocks,
34
- new MatchersOverTestLogic,
35
- new CommentsSayWhyNotWhat,
36
- new DocCommentsAddressUsers,
37
- new OneDirPerInterface,
38
- new DevServersFindAPort,
39
- new ReactiveOverUseState,
40
- new ResourcesAreDisposable
41
- ]
42
- });
43
-
44
- export { JUDGE_RULES };