@miroshnik/elves 0.0.0 → 2026.1018.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.
Files changed (68) hide show
  1. package/AGENTS.md +310 -0
  2. package/README.md +344 -0
  3. package/bin/ai-dev.ts +7 -0
  4. package/bin/elves.ts +2847 -0
  5. package/bin/shims/timeout +113 -0
  6. package/claude/CLAUDE.md +71 -0
  7. package/dist/github/scripts/github.js +3428 -0
  8. package/dist/spec/scripts/architecture.js +628 -0
  9. package/dist/spec/scripts/eslint-config.js +54 -0
  10. package/dist/spec/scripts/harness-qzb932c8.js +959 -0
  11. package/dist/spec/scripts/harness-v9s1v9w3.js +16045 -0
  12. package/dist/spec/scripts/harness.js +53 -0
  13. package/dist/spec/scripts/knip-hints.cjs +34 -0
  14. package/docs/ci-concurrency.md +82 -0
  15. package/docs/cloud-sessions.md +203 -0
  16. package/docs/judgment.md +81 -0
  17. package/docs/parallel-checkouts.md +220 -0
  18. package/docs/pr-checks.md +117 -0
  19. package/docs/testing.md +304 -0
  20. package/package.json +70 -1
  21. package/skills/ci-wait/SKILL.md +180 -0
  22. package/skills/ci-wait/scripts/wait-ci.sh +377 -0
  23. package/skills/dashboard/SKILL.md +212 -0
  24. package/skills/dashboard/scripts/dashboard.ts +912 -0
  25. package/skills/dashboard/scripts/sessions.ts +772 -0
  26. package/skills/est/SKILL.md +221 -0
  27. package/skills/est/reference.md +381 -0
  28. package/skills/est/scripts/est.ts +4854 -0
  29. package/skills/github/SKILL.md +206 -0
  30. package/skills/github/locales/en.json +449 -0
  31. package/skills/github/locales/ru.json +449 -0
  32. package/skills/github/reference.md +1073 -0
  33. package/skills/github/scripts/github.ts +4390 -0
  34. package/skills/github/scripts/locale.ts +495 -0
  35. package/skills/github/scripts/package.json +3 -0
  36. package/skills/slot/SKILL.md +145 -0
  37. package/skills/slot/scripts/package.json +3 -0
  38. package/skills/slot/scripts/slot.ts +279 -0
  39. package/skills/spec/SKILL.md +247 -0
  40. package/skills/spec/canon.md +219 -0
  41. package/skills/spec/checks.md +709 -0
  42. package/skills/spec/ci.md +378 -0
  43. package/skills/spec/migration.md +125 -0
  44. package/skills/spec/reference.md +889 -0
  45. package/skills/spec/scripts/architecture.ts +839 -0
  46. package/skills/spec/scripts/c4.ts +184 -0
  47. package/skills/spec/scripts/eslint-config.ts +82 -0
  48. package/skills/spec/scripts/harness.ts +1483 -0
  49. package/skills/spec/scripts/knip-hints.cjs +34 -0
  50. package/skills/spec/scripts/knip-hints.d.cts +17 -0
  51. package/skills/spec/scripts/package-run.ts +22 -0
  52. package/skills/spec/scripts/package.json +3 -0
  53. package/skills/spec/scripts/spec-break.ts +232 -0
  54. package/skills/spec/scripts/spec-claims.ts +198 -0
  55. package/skills/spec/scripts/spec-diff.ts +1111 -0
  56. package/skills/spec/scripts/spec-doc.ts +744 -0
  57. package/skills/spec/scripts/spec-exceptions.ts +233 -0
  58. package/skills/spec/scripts/spec-publish.ts +214 -0
  59. package/skills/spec/scripts/spec-run.ts +235 -0
  60. package/skills/spec/scripts/spec-shard.ts +267 -0
  61. package/skills/spec/scripts/speclib.ts +826 -0
  62. package/skills/spec/scripts/vendor/babel-parser.LICENSE +19 -0
  63. package/skills/spec/scripts/vendor/babel-parser.cjs +14615 -0
  64. package/skills/spec/scripts/vendor/babel-parser.d.cts +3 -0
  65. package/skills/task-env/SKILL.md +231 -0
  66. package/skills/task-env/proxy/compose.yaml +51 -0
  67. package/skills/task-env/reference.md +254 -0
  68. package/skills/task-env/scripts/task-env.ts +1017 -0
package/AGENTS.md ADDED
@@ -0,0 +1,310 @@
1
+ # Shared rules for all projects
2
+
3
+ ## This file and skills
4
+
5
+ The Elves canon for any agent (Claude Code, Codex, Gemini CLI, Cursor,
6
+ Copilot, OpenCode, Amp). It lives in **miroshnik/elves** with the skills
7
+ (`skills/*`) and references (`docs/`, next to this file), installed
8
+ onto the machine — README, "Installation". A rule or skill change from
9
+ another project's session is a task in Elves (project #6) without that
10
+ project's names, for a separate session; I don't edit an Elves clone from
11
+ someone else's session. A Claude Code **cloud session** sees only the
12
+ repository and its project hook's flow — `docs/cloud-sessions.md`.
13
+
14
+ **The repository is public:** no names, owners, paths or numbers of other
15
+ repositories, no colleagues or clients — in files, git history or issues;
16
+ examples are made up. **A skill is `SKILL.md` + `scripts/`** in TypeScript
17
+ under Bun (Agent Skills; README, "Repository layout"); repository specifics
18
+ — local configuration. **Budgets** (standard `canon-size`): this file ≤
19
+ 3,000 words, a `SKILL.md` ≤ 2,500, a skill description ≤ 1,024 characters.
20
+ Here — what always applies and where to go; reference — a skill's
21
+ `reference.md` or `--help`, `docs/`.
22
+
23
+ ## First step of a session — an up-to-date flow
24
+
25
+ Rules load at the session start, so before the task: `bunx
26
+ @miroshnik/elves check -g` (machine) and `check` (project, with its mode
27
+ and language). The machine's copy and a project's package version
28
+ follow Elves releases (tags `vYYYY.MM.DD`), a `--link` clone — `origin/main`;
29
+ a release is the owner's step (`elves release`), I cut one only when asked.
30
+
31
+ - **The machine is behind** — `update -g`. After an `update` I tell the user
32
+ briefly what changed (it lists the skipped releases) and re-read what was
33
+ updated: it applies, not what loaded at the start.
34
+ - **The project is behind** (or git ignores flow files) — `update` in the
35
+ task's branch: the package version, a few lines.
36
+ - **The project keeps a copy of the flow** — the move is a task of its own,
37
+ one per project (`check` prints its `github task new`): I recommend it and
38
+ ask whether to queue it.
39
+ - **`update` refused or the check unavailable** — I don't fix the clone; I
40
+ work by the current flow and say so.
41
+
42
+ ## Language
43
+
44
+ The flow is written in English; the agent works in the **project language**
45
+ (`language` in `.agents/elves.json`, printed by `check`): talking with the
46
+ user, issues, prompts to subagents, documents, commit and PR
47
+ descriptions, `describe`/`it` names, decision docs — briefly. Always English:
48
+ code, identifiers, terms, conventional-commit type and scope. Names that
49
+ scripts write to GitHub and parse back are exact — `locales/<language>.json`
50
+ of the `github` skill; in `en`: sections `## Questions`, `## Scenarios`;
51
+ `Status` `Backlog` → `In progress` → `Done`; the comment `State`; `Task #N`,
52
+ `epic #M` in a subagent's prompt; the last line `All
53
+ done. The session can be closed.` · `All done, but there are questions: …` ·
54
+ `Remaining: …`.
55
+
56
+ ## What I do without asking and what needs a yes
57
+
58
+ - **Without asking:** reading and search, tests, lint, typecheck, build, local
59
+ edits in my checkout, local infrastructure (Docker, dev database), logs and
60
+ read-only requests to external systems; task tracking; re-running my own CI
61
+ run, closing my own duplicate PR, deleting my own merged branch; updating
62
+ the flow and committing it.
63
+ - **Only on an explicit "yes"** — anything irreversible or external: `git
64
+ commit`, `git push`, merge, deploy, tag, migrations and writes to live
65
+ databases, external service settings, deleting others' or unmerged remote
66
+ branches and data, outgoing messages (auto mode — below).
67
+ - **Permission is for this action, this time:** "commit" ≠ "and push", "fix
68
+ whatever is needed" ≠ a merge, a past "yes" doesn't carry over; one
69
+ "commit" covers all current work in logical steps. A repository may set
70
+ another mode in its `AGENTS.md`. "Do it all yourself" lifts intermediate
71
+ confirmations for the named task, except on a discrepancy that changes
72
+ scope or approach. An autonomous routine does exactly what
73
+ its assignment names; merge, deploy, external settings — only if named.
74
+ - **`"auto": true` in `.agents/elves.json` — the whole task without asking**:
75
+ commit, push, fixing CI, merging my own PR on green checks; work outside the
76
+ task — a Backlog task and the question «queue it?». The task's open
77
+ questions — I answer by a recommendation with ✅ auto (`task answer
78
+ --auto`); my own question goes into the questions section the same way,
79
+ before code, not into chat. I ask only
80
+ without a clear recommendation, when the decision is critical or a human's,
81
+ or on a discrepancy that changes scope or approach — not when the answer
82
+ would be "yes" or "as you recommend". Anything else irreversible or
83
+ external still needs a "yes".
84
+ - **Secrets and bypassing protections — only with permission** (tokens, keys,
85
+ bypass secrets, disabling checks at the host, CI or cloud): first — what
86
+ will appear and where; a secret from chat — never stored, rotation reminded.
87
+
88
+ ## Task tracking
89
+
90
+ - Tasks live in the repository's **GitHub Issues**, not in local lists, TODO
91
+ files or the agent's task list; no repository — ask where. The `github`
92
+ skill runs them (`task new`, `show`, `answer`, `status`, `close`, `drop`,
93
+ `pr labels`), not `gh issue view`/`edit`; how tasks, the project and
94
+ milestones are organized — its `reference.md`.
95
+ - **Types:** Task (one PR), Bug, Epic (a personal account — the `epic`
96
+ label). **Decision labels** — the decision's name, kind by color: a task
97
+ carries those of the decisions it introduces or changes, an epic — their
98
+ union.
99
+ - **A big task is an epic** (prefix `<Prefix> · …`) **+ subtasks**
100
+ (sub-issues); **dependencies only as GitHub links** (sub-issue, blocked
101
+ by — on another repository's issue too; a blocker that isn't an issue — the
102
+ `external blocker` label, the reason in a comment): a task with an open
103
+ *blocked by* or that label isn't taken. Before creating — check it doesn't
104
+ exist (`gh issue list --search`).
105
+ - **What GitHub keeps natively isn't repeated in an issue's text** —
106
+ sub-issues, blocked by, `Status`, milestone, labels, fields, the PR: a copy
107
+ goes stale; an epic's description has no list of subtasks or stages.
108
+ - **One GitHub Project per repository**, named after it, with all tasks;
109
+ `project check` once per session, ❌ — `project fix`. `Status` I set
110
+ **myself, immediately**: `task status`, `task close`, `task drop` (won't
111
+ do, duplicate). `Priority` (`Urgent` → `Low`, `Medium` by default) is
112
+ required on an open task. A milestone (an epic stage, a release) I close
113
+ with its last task.
114
+
115
+ ### Session and branch — one task
116
+
117
+ - **Session = task:** `task status` won't take a second one. Another task —
118
+ Backlog and the question «queue #263?», "yes" — its executor at once;
119
+ "do it here" — a one-sentence refusal and the question again. My own
120
+ regression and a fix for a green PR are the same task. A new epic — the
121
+ question «run the dispatcher on epic #M?», without In progress.
122
+ - **A dispatcher** — "do all tasks of epic #M", "fix all High bugs", a "yes"
123
+ — any session, its task stays; one started for it — in the project folder,
124
+ not a worktree: executors start from `main`. `github task queue` — ready
125
+ ones with executors' prompts; an executor — a background subagent in its
126
+ worktree or a cloud session: at most 3 subagents and 5 cloud sessions at
127
+ once, the owner's number replaces either; its question — to the owner,
128
+ the answer into the issue and back; failed — a task comment, no restart.
129
+ - **The session is named `#<number> <task title>`** (without a task — by
130
+ meaning, no number) as soon as the task is clear (no tool — ask the user):
131
+ `est` links the session to the task by it.
132
+ - **Branch = `<type>/<issue>-<slug>`** (`feat/42-invoice-export`): `type` —
133
+ conventional-commit types (`feat fix docs refactor perf test chore ci
134
+ build`) plus `research` (a spike without code); slug — Latin kebab-case,
135
+ 2–5 words; a repository's area prefix goes first (`backend/fix/263-…`). A
136
+ branch named by a worktree tool is renamed before the first push by `github
137
+ task status <N> "In progress" --branch <type>/<N>-<slug>`.
138
+ - **PR:** the title is a conventional commit, the body has `Closes #263`.
139
+ **Merge — rebase only** (`gh pr merge <N> --rebase`): commits land in
140
+ `main`, each a conventional commit with `Refs #263` (`Closes` would close
141
+ the task). Without PRs — `Closes #N` in the last commit.
142
+
143
+ ### Open questions — at the start of work
144
+
145
+ A task's questions are a numbered list in its description's questions
146
+ section. Taking a task, **first of all** — before the plan, code and
147
+ subagents — I read the questions of the task and its epic (`github task show
148
+ <N>`) and **ask the user all open ones (without ✅)** in one message, each
149
+ with options and a recommendation. What already has an answer (comments,
150
+ code) gets ✅; my own questions join the message and the section. While
151
+ waiting I do what doesn't depend on the answer — what does, I neither start
152
+ nor replace with an assumption. The answer goes straight into the issue:
153
+ `github task answer <N> <k> "<answer>"`. An autonomous routine doesn't take a
154
+ task with open questions.
155
+
156
+ ### Estimate and actual — the `est` skill
157
+
158
+ The unit is the agent's hours on the task except waits for the user's input;
159
+ CI and check waits count, split out.
160
+ The estimate is set by `github task new`, the actual by `github task close`;
161
+ neither is written by hand, the estimate isn't rewritten after
162
+ work starts, no actual — "actual unavailable", not a number by eye. Work is
163
+ linked to the task by the pinned session, the session name, the branch,
164
+ `Closes #N` and the task number in every subagent's assignment ("Subagents
165
+ and worktrees") — otherwise there is no actual.
166
+
167
+ ### Epic refresh on task close
168
+
169
+ Once a task is merged, **a subagent with a fresh context** brings the open
170
+ tasks of its epic in line with what shipped — not the session at peak
171
+ context: `github task actualize <N>` does the mechanics and prints its prompt,
172
+ in the same turn as `ci-wait merged <PR>` in the background; after both —
173
+ `github task close`. The last line of the answer ("Language"): merged,
174
+ deployed, branch removed, epic refreshed, no questions — "all done, can be
175
+ closed"; the owner has something to decide — "all done, but there are
176
+ questions" with them; otherwise — "remaining" with what the session waits for
177
+ and from whom. In auto mode after "can be closed" the session archives itself
178
+ where the agent has the tool; information without a decision doesn't prevent
179
+ it.
180
+
181
+ ## Git, PRs and merging
182
+
183
+ - **Taking a task** — check it isn't going in a parallel session (an open PR,
184
+ a branch `*/<N>-*` after `git fetch --prune`): continue that work or wait
185
+ for the merge; two PRs for one thing — close the second.
186
+ - **Branch only from a fresh `origin/main`** (`git fetch origin && git switch
187
+ -c feat/263-slug origin/main --no-track`). Into `main` only via a PR; a
188
+ direct push and `gh pr merge --admin` — only on the owner's direct
189
+ instruction. **Before a push** — is it my branch.
190
+ - **Commits in logical steps**, tests in the same commit as the code.
191
+ **Before a commit — `lint`, `typecheck`, `test:spec`; `test` — what the
192
+ change affects** (`--changed=origin/main`; the full run — CI,
193
+ `docs/testing.md`); before merging — a full build; `set -o pipefail` in
194
+ `script | tail`.
195
+ - **I merge as soon as all checks are green** (the preview deploy too; an
196
+ empty list is "not registered yet") and GitHub merges without a conflict;
197
+ rebase and `--force-with-lease` — only on a textual conflict or my own
198
+ changes. **Before merging — `github pr premerge`:** `main` moved after the
199
+ PR's CI — fast checks on the merge with it; red — I fix the root cause;
200
+ `main` red by itself (exit code 3) — no merge and no fix in the PR: one bug
201
+ for it, I wait for it to close.
202
+ - A merge that deploys — I wait for the deploy on the merge SHA (`ci-wait`),
203
+ the epic refresh in parallel; **then `github task close`**. Others'
204
+ branches, stacks and unmerged work I don't touch.
205
+ - Mechanics — the `github` skill, "Git, PRs and merging — mechanics";
206
+ waiting for checks and deploys — `docs/pr-checks.md`.
207
+
208
+ ## Specification — decisions
209
+
210
+ A project's spec is **decisions with a mechanical check**, functional and
211
+ non-functional (a test, a lint rule, an architecture check).
212
+ **No check — no decision; no decision — no code:** behavior without a check
213
+ may change without agreement; code no decision claims is dead. A check is
214
+ written before the code and is red first (acceptance), then holds the
215
+ decision (regression); a decision changes through its check — first the
216
+ check, red, then the code. Three roots of `tests/` by the reader's question:
217
+ `capabilities/<name>` (what the system does), `architecture` (what it's made
218
+ of — a model with checks), `standards/<name>` (code rules, cross-cutting
219
+ qualities); a decision is a folder (`<folder>.md` — why, `<folder>.test.ts` —
220
+ the statements). Exceptions — a mark in the element's file or a file in the
221
+ folder's `exceptions/`, with an `#issue`, a reason and a ratchet. Test names
222
+ are statements in the project language; a code task gets the scenarios
223
+ section (future `it` names) before code. The PR body is `spec-diff` output;
224
+ docs are generated (`spec-doc`) and published by CI to the `spec` branch. A
225
+ recurring decision — a "Standard · …" issue and a rule in `tests/standards/`.
226
+ The full canon and wiring — the `spec` skill (`canon.md`, `checks.md`).
227
+
228
+ ## Tests and code
229
+
230
+ - **A test failed — I fix the root cause** (the test or the logic), even if
231
+ unrelated to my changes or a rerun is green — no "pre-existing flake",
232
+ timeouts or retries; a race goes by its cause (the real event, not a
233
+ pause). A flake suspicion — the same run on the base branch: red there too
234
+ — I compare the delta.
235
+ - **A run's result — by the runner's summary**, not the wrapper's exit code.
236
+ Project checks go through the machine queue (the `slot` skill), a full run
237
+ — in the background; e2e and UI in a browser — `docs/testing.md`.
238
+ - **A regression test and a "no defect" guard must be able to fail**: I
239
+ revert the fix, see red, restore it; it didn't fail — it guards against
240
+ overcorrection (named so) or is deleted.
241
+ - **An external API contract — by its schema or docs**, not intuition; on a
242
+ mismatch I fix the test, not the code.
243
+ - **Intentionally different behavior in two places** — mirrored comments
244
+ with the reason.
245
+ - **I check what reached the human** (the delivered email, the page at the
246
+ recipient), not my output; a component on several surfaces — in each.
247
+ - **Judgment:** before a run — which of our mistakes would give the same
248
+ outcome; labels — after checking what the numbers mean; I edit exactly
249
+ what was named; "doesn't reproduce" — with what I measured.
250
+ `docs/judgment.md`.
251
+
252
+ ## Production and debugging
253
+
254
+ - **The production database is read-only.** Data and schema change via a
255
+ migration in a PR; DDL on production — only on
256
+ the owner's direct instruction, as a migration file; the environment
257
+ refuses — I explain, no workaround. Data the application manages (roles,
258
+ permissions, audited settings) never changes by direct DML: the audit is
259
+ lost, guards bypassed; what the UI lacks is a code change.
260
+ - **Production numbers — first, is it the right database:** the first query
261
+ checks it against the repository (migrations, columns, orders of
262
+ magnitude); no match — stop.
263
+ - **"Didn't help" → production facts, not a third reproduction:** the logs
264
+ of the real request and production data (the row, `updated_at`, audit),
265
+ then a new hypothesis.
266
+
267
+ ## Subagents and worktrees
268
+
269
+ - **Subagents don't share a dirty worktree.** An agent that may install
270
+ packages or touch files "to try" gets an isolated worktree or "read-only
271
+ plus a temp folder" without `git checkout/restore/stash/clean`: its cleanup
272
+ reverts everything uncommitted, others' work too. Several agents in one
273
+ worktree — non-overlapping files, no git, a shared file has one owner. After
274
+ a fan-out — `git status` and `git diff --stat`. Temp files shared with
275
+ subagents get a unique prefix (task, role).
276
+ - **A fresh worktree lacks untracked files** (dependencies, `.env*.local`) —
277
+ I install and copy them. Paths in commands and assignments lead into the
278
+ worktree (a path "from memory" edits `main`); `git -C <worktree> status`
279
+ before and after an edit.
280
+ - **Parallel checkouts share ports, databases and `.git/config`:** the task's
281
+ apps, databases and e2e run in its own Compose stack (the `task-env`
282
+ skill) at `<service>.<N>.<project>.localhost`, not on a host port; others'
283
+ stacks and busy ports I don't touch — `docs/parallel-checkouts.md`.
284
+ - **A subagent gets a unit of ~50 turns** (one decision's folder, one file,
285
+ one spec), not a 200-turn zone: it carries the same preamble (≈ 100k
286
+ tokens), and its price is quadratic in turns. The assignment has the task
287
+ number after the word for "task" or at the start, the epic after the word
288
+ for "epic" ("Language") — so `est` links its work. **Fewer turns:** a file
289
+ in one full read, independent tool calls in one turn.
290
+
291
+ ## Project knowledge and handoff
292
+
293
+ - **Shared — in Elves, project-specific — in the project's spec**
294
+ ("Specification — decisions"), the reason in the decision's `<folder>.md`;
295
+ neither shared nor checkable (operations, product documents) — the
296
+ project's `docs/`. The project's `AGENTS.md` — the install block and how
297
+ its mode differs. An agreement from chat goes there too, not into the
298
+ agent's memory: memory is a cache, not a source.
299
+ - **I don't revisit the stack** or drag in dependencies; something in the way
300
+ — a question to the user, not a silent replacement. Versions — latest
301
+ stable; a tool question — its official documentation first.
302
+ - **Before a pause or an agent change — a State comment in the issue:** done,
303
+ the branch, next, blockers.
304
+
305
+ ## CI: parallel tasks
306
+
307
+ Branches and PRs run in parallel, only my own stale run of a branch is
308
+ cancelled; `main`, tags and manual runs never (`queue: max`); deploy — a
309
+ queue per environment, apart from CI; others' runs I don't cancel or re-run.
310
+ Workflow fragments — `docs/ci-concurrency.md`.