@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.
- package/AGENTS.md +310 -0
- package/README.md +344 -0
- package/bin/ai-dev.ts +7 -0
- package/bin/elves.ts +2847 -0
- package/bin/shims/timeout +113 -0
- package/claude/CLAUDE.md +71 -0
- package/dist/github/scripts/github.js +3428 -0
- package/dist/spec/scripts/architecture.js +628 -0
- package/dist/spec/scripts/eslint-config.js +54 -0
- package/dist/spec/scripts/harness-qzb932c8.js +959 -0
- package/dist/spec/scripts/harness-v9s1v9w3.js +16045 -0
- package/dist/spec/scripts/harness.js +53 -0
- package/dist/spec/scripts/knip-hints.cjs +34 -0
- package/docs/ci-concurrency.md +82 -0
- package/docs/cloud-sessions.md +203 -0
- package/docs/judgment.md +81 -0
- package/docs/parallel-checkouts.md +220 -0
- package/docs/pr-checks.md +117 -0
- package/docs/testing.md +304 -0
- package/package.json +70 -1
- package/skills/ci-wait/SKILL.md +180 -0
- package/skills/ci-wait/scripts/wait-ci.sh +377 -0
- package/skills/dashboard/SKILL.md +212 -0
- package/skills/dashboard/scripts/dashboard.ts +912 -0
- package/skills/dashboard/scripts/sessions.ts +772 -0
- package/skills/est/SKILL.md +221 -0
- package/skills/est/reference.md +381 -0
- package/skills/est/scripts/est.ts +4854 -0
- package/skills/github/SKILL.md +206 -0
- package/skills/github/locales/en.json +449 -0
- package/skills/github/locales/ru.json +449 -0
- package/skills/github/reference.md +1073 -0
- package/skills/github/scripts/github.ts +4390 -0
- package/skills/github/scripts/locale.ts +495 -0
- package/skills/github/scripts/package.json +3 -0
- package/skills/slot/SKILL.md +145 -0
- package/skills/slot/scripts/package.json +3 -0
- package/skills/slot/scripts/slot.ts +279 -0
- package/skills/spec/SKILL.md +247 -0
- package/skills/spec/canon.md +219 -0
- package/skills/spec/checks.md +709 -0
- package/skills/spec/ci.md +378 -0
- package/skills/spec/migration.md +125 -0
- package/skills/spec/reference.md +889 -0
- package/skills/spec/scripts/architecture.ts +839 -0
- package/skills/spec/scripts/c4.ts +184 -0
- package/skills/spec/scripts/eslint-config.ts +82 -0
- package/skills/spec/scripts/harness.ts +1483 -0
- package/skills/spec/scripts/knip-hints.cjs +34 -0
- package/skills/spec/scripts/knip-hints.d.cts +17 -0
- package/skills/spec/scripts/package-run.ts +22 -0
- package/skills/spec/scripts/package.json +3 -0
- package/skills/spec/scripts/spec-break.ts +232 -0
- package/skills/spec/scripts/spec-claims.ts +198 -0
- package/skills/spec/scripts/spec-diff.ts +1111 -0
- package/skills/spec/scripts/spec-doc.ts +744 -0
- package/skills/spec/scripts/spec-exceptions.ts +233 -0
- package/skills/spec/scripts/spec-publish.ts +214 -0
- package/skills/spec/scripts/spec-run.ts +235 -0
- package/skills/spec/scripts/spec-shard.ts +267 -0
- package/skills/spec/scripts/speclib.ts +826 -0
- package/skills/spec/scripts/vendor/babel-parser.LICENSE +19 -0
- package/skills/spec/scripts/vendor/babel-parser.cjs +14615 -0
- package/skills/spec/scripts/vendor/babel-parser.d.cts +3 -0
- package/skills/task-env/SKILL.md +231 -0
- package/skills/task-env/proxy/compose.yaml +51 -0
- package/skills/task-env/reference.md +254 -0
- package/skills/task-env/scripts/task-env.ts +1017 -0
|
@@ -0,0 +1,449 @@
|
|
|
1
|
+
{
|
|
2
|
+
"issueTypes": {
|
|
3
|
+
"task": "Task",
|
|
4
|
+
"bug": "Bug",
|
|
5
|
+
"epic": "Epic"
|
|
6
|
+
},
|
|
7
|
+
"sections": {
|
|
8
|
+
"questions": "## Questions",
|
|
9
|
+
"scenarios": "## Scenarios"
|
|
10
|
+
},
|
|
11
|
+
"labels": {
|
|
12
|
+
"questions": "questions",
|
|
13
|
+
"questionsDescription": "Open questions in the «## Questions» section",
|
|
14
|
+
"epicDescription": "Epic: a large task with subtasks",
|
|
15
|
+
"externalBlocker": "external blocker"
|
|
16
|
+
},
|
|
17
|
+
"status": {
|
|
18
|
+
"backlog": "Backlog",
|
|
19
|
+
"inProgress": "In progress",
|
|
20
|
+
"done": "Done"
|
|
21
|
+
},
|
|
22
|
+
"fields": {
|
|
23
|
+
"estimate": "Estimate, h",
|
|
24
|
+
"actual": "Actual, h",
|
|
25
|
+
"tokens": "Tokens, M",
|
|
26
|
+
"cost": "Cost, $"
|
|
27
|
+
},
|
|
28
|
+
"views": {
|
|
29
|
+
"board": "Board",
|
|
30
|
+
"table": "Table",
|
|
31
|
+
"roadmap": "Roadmap"
|
|
32
|
+
},
|
|
33
|
+
"labelMarkers": {
|
|
34
|
+
"decision": "Decision:",
|
|
35
|
+
"slice": "Slice:",
|
|
36
|
+
"architecturePath": "tests/architecture — rule or module {name}"
|
|
37
|
+
},
|
|
38
|
+
"comments": {
|
|
39
|
+
"state": "State",
|
|
40
|
+
"actual": "Actual:",
|
|
41
|
+
"closedByPr": "Closed by PR {prs}: GitHub didn't link the PR to the task",
|
|
42
|
+
"externalBlocker": "External blocker:"
|
|
43
|
+
},
|
|
44
|
+
"subagentPrompt": {
|
|
45
|
+
"task": "Task",
|
|
46
|
+
"epic": "epic"
|
|
47
|
+
},
|
|
48
|
+
"mainRed": {
|
|
49
|
+
"title": "{base} is red",
|
|
50
|
+
"check": "check {names}",
|
|
51
|
+
"checks": "checks {names}"
|
|
52
|
+
},
|
|
53
|
+
"actualize": {
|
|
54
|
+
"lead": "{task} #{number} ({epicWord} #{epic}): epic refresh after the merge — bring the epic's open tasks in line with what shipped.",
|
|
55
|
+
"fetch": "The whole assignment — the texts of the epic's open tasks, the PR files, what the script named, the checks by meaning — is printed by `{command}`: run it first, outside the sandbox (gh doesn't work in it); don't collect the tasks and the PR yourself.",
|
|
56
|
+
"shipped": "Repository {repo}. Shipped: #{number} «{title}», {shipped}.",
|
|
57
|
+
"prs": "PR {list}",
|
|
58
|
+
"noPr": "no PR found — commits {command}",
|
|
59
|
+
"files": "PR #{pr} files:",
|
|
60
|
+
"epic": "## Epic #{epic} «{title}»",
|
|
61
|
+
"openTasks": "## The epic's open tasks — its sub-issues, not a list in the epic's description",
|
|
62
|
+
"openTask": "### #{number} «{title}»",
|
|
63
|
+
"noBody": "(no description)",
|
|
64
|
+
"copies": "## Copies of links in text — remove them: GitHub keeps the links (sub-issue, blocked by)",
|
|
65
|
+
"copy": "- #{number}: «{line}»",
|
|
66
|
+
"answers": "## Answers to open questions in comments — check that it answers that question and move it into «{questions}» (✅ and the answer at the question, same numbering); if not — leave it",
|
|
67
|
+
"commentAnswer": "- #{number}, question {k}: «{text}» — {url}",
|
|
68
|
+
"checks": "## Checks by meaning — yours (canon — reference.md of the github skill, «Epic refresh on task close»); the mechanics — blocked by on done tasks, the questions label without open questions, milestones without open tasks — the script did",
|
|
69
|
+
"scope": "You change only GitHub tasks — description, «{questions}», links, status; the github skill script — `{script}`: not done — `task drop <N>`, a new one — `task new … --branch-type <type> --epic {epic}` (it sets the estimate itself); an answer at a question — `task answer <N> <k> \"<answer>\"`. Don't touch code, branches or git; don't close #{number}, epic #{epic} or their milestones — task close does that after you.",
|
|
70
|
+
"comment": "The result — always, as the last step: a comment on epic #{epic} (`gh issue comment {epic} --repo {repo}`), one line «{report}» — after the colon what you fixed, nothing to fix — «the block is current». By it `task close {number}` sees the refresh is over: without it the close refuses.",
|
|
71
|
+
"answer": "Answer — fixes one per line with task numbers and questions to the owner, if any; otherwise «The block is current».",
|
|
72
|
+
"linkWords": "blocked by|blocks|after|depends on|waits for",
|
|
73
|
+
"report": "Refresh after #{number}, result: {text}",
|
|
74
|
+
"mechanics": "Refresh after #{number}, script: {fixes}.",
|
|
75
|
+
"unblocked": "#{task}: blocked by done {blockers} removed",
|
|
76
|
+
"unlabeled": "#{task}: label «{label}» removed — no open questions",
|
|
77
|
+
"milestone": "milestone «{title}» closed — no open tasks in it"
|
|
78
|
+
},
|
|
79
|
+
"queue": {
|
|
80
|
+
"prompt": "{task} #{number} in {repo}{epic}: you are an executor of the dispatcher session. The whole assignment is printed by `{command}` — call it first, outside the sandbox (gh doesn't work in it).",
|
|
81
|
+
"epic": " ({epicWord} #{epic})",
|
|
82
|
+
"lead": "{task} #{number} «{title}» in {repo}{epic}: you are an executor of the dispatcher session — do the task whole by the canon, like a session in auto mode: the task's questions, `{script} task status {number} \"{inProgress}\" --branch <type>/{number}-<slug>`, the branch from a fresh origin/main, code and tests, PR, green CI, `pr premerge`, merge, deploy, the epic refresh, `{script} task close {number}`.",
|
|
83
|
+
"resume": "The task is already «{inProgress}» and has a branch {branches} — a restart: continue its work. The branch is checked out in another worktree (`git worktree list`) — work in that one, not in your new one: in Claude Code — `EnterWorktree` with its path; uncommitted work — `git status` there. In no worktree — check it out in yours.",
|
|
84
|
+
"subagent": "You are a subagent, not a session:",
|
|
85
|
+
"session": "- don't rename or archive the session and don't write the last line («{done}») — the dispatcher does;",
|
|
86
|
+
"wait": "- wait for CI and the deploy with a regular call, not in the background: a background command doesn't wake a subagent, and a Bash call lives up to 10 minutes — `{waitCi} pr <PR> --timeout 540` (after the merge — `merged <PR>`), on TIMEOUT — the same call again;",
|
|
87
|
+
"git": "- git — in separate calls, without `cd`, `&&` and `|`: worktree isolation refuses a compound command with git;",
|
|
88
|
+
"subagents": "- writing subagents — launch as needed, no limit: each gets its own worktree and «{task} #{number}» at the start of its prompt (`est` links its work by it); bring their commits into your branch, remove their worktrees and branches yourself after the merge — what didn't go, name in the answer;",
|
|
89
|
+
"live": "- while any of your subagents works, don't answer: wait for their answers — a background subagent wakes you with its answer; an answer with live subagents looks like a failure, and the dispatcher would give the task to a second executor next to you. Can't wait — answer `waits for subagents: <which and what they do>`: it isn't `failed`, there will be no second executor;",
|
|
90
|
+
"found": "- work found outside the task — `{script} task new …` (work of the task's epic — with `--epic`: the dispatcher picks it up) — name it in the answer: whether to queue it is the owner's call;",
|
|
91
|
+
"question": "- a question without a clear recommendation — into «{questions}» of the task; don't start the code that depends on it and answer the dispatcher: the owner's answer comes back here.",
|
|
92
|
+
"answer": "The answer to the dispatcher — one line: `merged #<PR>` · `question: <the question, options, recommendation>` · `waits for subagents: <which and what they do>` · `failed: <what stopped and where>`.",
|
|
93
|
+
"alive": "{task} #{number} in {repo}: the task's previous executor or its subagent is alive — the `!` lines above. Don't take the task and change nothing: answer the dispatcher in one line `waits for the previous executor: <the worktree and why it is alive>` — the dispatcher restarts the task only when no worktree of the previous executor and its subagents is locked by a live process or gets commits.",
|
|
94
|
+
"cloudEpic": " ({epicWord} {epic})",
|
|
95
|
+
"cloud": "{task} #{number} «{title}» in {repo}{epic}: you are a cloud executor of the dispatcher session — do the task whole by the canon, like a session in auto mode: the task's questions, code and tests, PR, green CI, merge, deploy.",
|
|
96
|
+
"cloudDoc": "- the cloud — by `docs/cloud-sessions.md` of the canon, read it first: of the github skill's scripts `task show`, `task answer` and `task new` work there (over REST), the rest refuse, the scenarios section — by editing the description over REST, project fields aren't set from the cloud; the branch is the one the cloud assigned, don't rename it;",
|
|
97
|
+
"cloudClose": "- after the merge — its section «Closing a task from the cloud»: the «{actual}» comment of `est fact {number}` and a «{state}» comment with what the cloud can't do — both into the task;",
|
|
98
|
+
"cloudDispatcher": "- the dispatcher waits for the task to close and closes it locally — the actual, the status, the merged branch, archiving this session: don't message it, don't archive the session;",
|
|
99
|
+
"cloudQuestion": "- a question without a clear recommendation — into «{questions}» of the task and to the owner in this session, don't start the code that depends on it; stopped (a question, a failure, a limit) — a «{state}» comment into the task."
|
|
100
|
+
},
|
|
101
|
+
"est": {
|
|
102
|
+
"answer": "Answer",
|
|
103
|
+
"manual": "+ manually:",
|
|
104
|
+
"reason": "Reason:",
|
|
105
|
+
"hours": "h",
|
|
106
|
+
"closingWords": "close closes closed fix fixes fixed resolve resolves resolved",
|
|
107
|
+
"stopWords": "the and for with from into",
|
|
108
|
+
"fact": {
|
|
109
|
+
"unavailable": "Actual unavailable: no sessions found (coverage none).",
|
|
110
|
+
"body": "{h} h active in {agents} ({estimate}). {sessions}, {prompts},{subagents} wall {wall} h, coverage {cov}.",
|
|
111
|
+
"estimate": "estimate {h} h{ratio}",
|
|
112
|
+
"noEstimate": "no estimate",
|
|
113
|
+
"sessions": {
|
|
114
|
+
"one": "session",
|
|
115
|
+
"few": "sessions",
|
|
116
|
+
"many": "sessions",
|
|
117
|
+
"other": "sessions"
|
|
118
|
+
},
|
|
119
|
+
"prompts": {
|
|
120
|
+
"one": "prompt",
|
|
121
|
+
"few": "prompts",
|
|
122
|
+
"many": "prompts",
|
|
123
|
+
"other": "prompts"
|
|
124
|
+
},
|
|
125
|
+
"subagents": {
|
|
126
|
+
"one": "subagent",
|
|
127
|
+
"few": "subagents",
|
|
128
|
+
"many": "subagents",
|
|
129
|
+
"other": "subagents"
|
|
130
|
+
},
|
|
131
|
+
"commits": {
|
|
132
|
+
"one": "commit",
|
|
133
|
+
"few": "commits",
|
|
134
|
+
"many": "commits",
|
|
135
|
+
"other": "commits"
|
|
136
|
+
},
|
|
137
|
+
"prs": " PR {list};",
|
|
138
|
+
"noPr": " no PR;",
|
|
139
|
+
"diff": " {commits}, diff {diff}.",
|
|
140
|
+
"diffLines": "{n} lines",
|
|
141
|
+
"diffNa": "n/a (no PR)",
|
|
142
|
+
"shared": "shared {unit} with {list} (share 1/{k})",
|
|
143
|
+
"commitUnit": "commit {oid}",
|
|
144
|
+
"taken": " Not counted again: {h} h already in the actual of #{issue}.",
|
|
145
|
+
"overlap": " Overlap with the actual of #{issue}: {h} h — recompute #{issue}.",
|
|
146
|
+
"cloudMissing": " Cloud session https://claude.ai/code/{sid} not imported — est cloud-import.",
|
|
147
|
+
"tokens": "Tokens: {total} M",
|
|
148
|
+
"tokensSplit": " (input {in} · output {out} · cache write {cw} · cache read {cr})",
|
|
149
|
+
"cost": "; cost at API rates ≈ ${usd}",
|
|
150
|
+
"unpriced": "; no price (not in the price list): {models}",
|
|
151
|
+
"steps": "Turns: {n} (subagents {agents}, their turns {agentSteps}), preamble {preamble}K, context at the end {end}K, turns with context > {tail}K — {share} %.",
|
|
152
|
+
"waits": "Waits: CI {ci} min · after the merge {merged} · checks {checks}{slot} · rest {rest}.",
|
|
153
|
+
"waitsSlot": " (slot queue {slot})",
|
|
154
|
+
"and": " and ",
|
|
155
|
+
"cloudAgent": "a Claude Code cloud session"
|
|
156
|
+
},
|
|
157
|
+
"cloud": {
|
|
158
|
+
"actual": "Actual (cloud):",
|
|
159
|
+
"body": "{h} h active in a Claude Code cloud session, {prompts}.",
|
|
160
|
+
"tokens": " Tokens: {total} M{cost}.",
|
|
161
|
+
"cost": ", at API rates ≈ ${usd}",
|
|
162
|
+
"fields": " Session: https://claude.ai/code/{sid}. The local session sets the project fields: est fact {number} --write.",
|
|
163
|
+
"unavailable": "Actual unavailable (cloud): the task was done in a Claude Code cloud session — est can't see the GitHub project there; a local session gives the number by importing this session's events (est cloud-import) (coverage none).",
|
|
164
|
+
"session": " Session: https://claude.ai/code/{sid}."
|
|
165
|
+
},
|
|
166
|
+
"estimate": {
|
|
167
|
+
"headline": "Estimate: {h} h",
|
|
168
|
+
"tokens": ", ≈ {tok}M tokens",
|
|
169
|
+
"partial": " (tokens and cost from {k} of {n} analogs)",
|
|
170
|
+
"body": "{headline} (type {type}, confidence {conf}; {basis}). Analogs{auto}: {analogs}.{correction}{spread} {k}.",
|
|
171
|
+
"auto": " (picked by the script)",
|
|
172
|
+
"forecast": "forecast from the analogs' actuals",
|
|
173
|
+
"expertOver": "expert estimate; the analogs would give {h} h, tokens and cost rescaled ×{ratio}",
|
|
174
|
+
"expert": "expert estimate, no analogs with an actual",
|
|
175
|
+
"spread": " The analogs' actuals spread {min}…{max} h — the median is taken.",
|
|
176
|
+
"correction": " Correction: ×{mult}{note}.",
|
|
177
|
+
"tokCorrection": " Token and cost correction: ×{mult}{note}.",
|
|
178
|
+
"k": "k={k} (n={n}, level «{level}»; for reference, not applied to the forecast)",
|
|
179
|
+
"noK": "k: no history",
|
|
180
|
+
"levelRepo": "repo",
|
|
181
|
+
"levelAll": "all repos",
|
|
182
|
+
"none": "none",
|
|
183
|
+
"otherProject": "from project {repo}: {list}",
|
|
184
|
+
"analog": "{label} (actual {h} h{why})",
|
|
185
|
+
"unknown": "{label} (actual unknown)",
|
|
186
|
+
"partialCoverage": "{label} (actual {h} h, coverage {cov} — not counted)",
|
|
187
|
+
"notInProject": "{label} (not in the project)",
|
|
188
|
+
"labels": {
|
|
189
|
+
"one": "label",
|
|
190
|
+
"few": "labels",
|
|
191
|
+
"many": "labels",
|
|
192
|
+
"other": "labels"
|
|
193
|
+
},
|
|
194
|
+
"type": "type {type}",
|
|
195
|
+
"words": {
|
|
196
|
+
"one": "word",
|
|
197
|
+
"few": "words",
|
|
198
|
+
"many": "words",
|
|
199
|
+
"other": "words"
|
|
200
|
+
},
|
|
201
|
+
"size": "description ×{ratio}"
|
|
202
|
+
}
|
|
203
|
+
},
|
|
204
|
+
"updateCommit": "Elves flow {version}",
|
|
205
|
+
"updateTask": "Update the Elves flow",
|
|
206
|
+
"formerly": {
|
|
207
|
+
"updateTask": "Update the ai-dev flow"
|
|
208
|
+
},
|
|
209
|
+
"standardIssue": "Standard ·",
|
|
210
|
+
"autoAnswer": "✅ auto",
|
|
211
|
+
"lastLine": {
|
|
212
|
+
"done": "All done. The session can be closed.",
|
|
213
|
+
"questions": "All done, but there are questions:",
|
|
214
|
+
"remaining": "Remaining:"
|
|
215
|
+
},
|
|
216
|
+
"prSpecSection": "## Spec (tests)",
|
|
217
|
+
"spec": {
|
|
218
|
+
"tests": {
|
|
219
|
+
"one": "test",
|
|
220
|
+
"few": "tests",
|
|
221
|
+
"many": "tests",
|
|
222
|
+
"other": "tests"
|
|
223
|
+
},
|
|
224
|
+
"lint": {
|
|
225
|
+
"allRules": "all rules",
|
|
226
|
+
"noReason": "no reason"
|
|
227
|
+
},
|
|
228
|
+
"doc": {
|
|
229
|
+
"mark": "<!-- spec-doc: generated from test names, don't edit by hand -->",
|
|
230
|
+
"title": "Specification",
|
|
231
|
+
"intro": "Generated from the `tests/` tree, test names and their JSDoc (the `spec` skill, `spec-doc`). Don't edit by hand: edit the tests.",
|
|
232
|
+
"capabilities": "What the system does",
|
|
233
|
+
"architecture": "What it's made of",
|
|
234
|
+
"standards": "Which rules the code obeys",
|
|
235
|
+
"skippedCount": {
|
|
236
|
+
"one": "skipped",
|
|
237
|
+
"few": "skipped",
|
|
238
|
+
"many": "skipped",
|
|
239
|
+
"other": "skipped"
|
|
240
|
+
},
|
|
241
|
+
"failingCount": {
|
|
242
|
+
"one": "failing",
|
|
243
|
+
"few": "failing",
|
|
244
|
+
"many": "failing",
|
|
245
|
+
"other": "failing"
|
|
246
|
+
},
|
|
247
|
+
"variants": {
|
|
248
|
+
"one": "variant",
|
|
249
|
+
"few": "variants",
|
|
250
|
+
"many": "variants",
|
|
251
|
+
"other": "variants"
|
|
252
|
+
},
|
|
253
|
+
"skipped": "skipped",
|
|
254
|
+
"failing": "failing",
|
|
255
|
+
"todo": "todo",
|
|
256
|
+
"outside": "Outside the tree",
|
|
257
|
+
"outsideIntro": "Tests without a home in {homes} and {last} — move them:",
|
|
258
|
+
"none": "— none.",
|
|
259
|
+
"rules": "Rules"
|
|
260
|
+
},
|
|
261
|
+
"c4": {
|
|
262
|
+
"title": "Architecture",
|
|
263
|
+
"intro": "Generated from the model `tests/architecture/model.ts` (the `spec` skill, `spec-doc`): C4 diagrams and a table of modules. Edit the model; the architecture rules check it against the code.",
|
|
264
|
+
"system": "System",
|
|
265
|
+
"context": "System and external systems",
|
|
266
|
+
"containers": "Containers",
|
|
267
|
+
"components": "Modules",
|
|
268
|
+
"perimeter": "perimeter",
|
|
269
|
+
"viaModule": "via module {modules}",
|
|
270
|
+
"viaModules": "via modules {modules}",
|
|
271
|
+
"uses": "uses",
|
|
272
|
+
"dependsOn": "depends on",
|
|
273
|
+
"calls": "calls",
|
|
274
|
+
"library": "library",
|
|
275
|
+
"table": "| Module | Purpose | Directory | API | Depends on | Packages |",
|
|
276
|
+
"summary": "model: {parts}",
|
|
277
|
+
"moduleCount": {
|
|
278
|
+
"one": "module",
|
|
279
|
+
"few": "modules",
|
|
280
|
+
"many": "modules",
|
|
281
|
+
"other": "modules"
|
|
282
|
+
},
|
|
283
|
+
"containerCount": {
|
|
284
|
+
"one": "container",
|
|
285
|
+
"few": "containers",
|
|
286
|
+
"many": "containers",
|
|
287
|
+
"other": "containers"
|
|
288
|
+
},
|
|
289
|
+
"externalCount": {
|
|
290
|
+
"one": "external system",
|
|
291
|
+
"few": "external systems",
|
|
292
|
+
"many": "external systems",
|
|
293
|
+
"other": "external systems"
|
|
294
|
+
}
|
|
295
|
+
},
|
|
296
|
+
"diff": {
|
|
297
|
+
"base": "_Base: `{base}`._",
|
|
298
|
+
"unchanged": "Tests didn't change.",
|
|
299
|
+
"removed": "Removed",
|
|
300
|
+
"changed": "Changed",
|
|
301
|
+
"added": "Added",
|
|
302
|
+
"empty": "**{title}:** none.",
|
|
303
|
+
"outsideMark": "outside the tree",
|
|
304
|
+
"moved": "**Moved into the tree ({n}):** the same names as outside `{tests}/` on the base; from {files}.",
|
|
305
|
+
"movedFolder": "{tests} from {files}",
|
|
306
|
+
"files": {
|
|
307
|
+
"one": "file",
|
|
308
|
+
"few": "files",
|
|
309
|
+
"many": "files",
|
|
310
|
+
"other": "files"
|
|
311
|
+
},
|
|
312
|
+
"summary": "**Summary by folder** — {tests}, over the threshold of {limit}: the full list — `spec-diff --full` (in CI — the job summary).",
|
|
313
|
+
"folder": "Folder",
|
|
314
|
+
"harnessColumn": "Of them, from the harness",
|
|
315
|
+
"total": "Total",
|
|
316
|
+
"outsideFiles": "**Outside the `{tests}/` tree** changed test files: {files}.",
|
|
317
|
+
"notStatements": "⚠️ **Names that aren't statements: {n}** — new in this PR; `spec-doc` names them in warnings.",
|
|
318
|
+
"scenarios": "Task scenarios",
|
|
319
|
+
"noScenarios": "The issue has no `{section}` section — nothing to check against.",
|
|
320
|
+
"becameTests": "**Became tests ({n}):** in the lists above.",
|
|
321
|
+
"noTest": "no test",
|
|
322
|
+
"extraMark": "beyond scenarios",
|
|
323
|
+
"extraTitle": "Tests beyond scenarios",
|
|
324
|
+
"extraListed": "in the lists above, with the «{mark}» mark.",
|
|
325
|
+
"extraFull": "as a list — `spec-diff --full`.",
|
|
326
|
+
"harnessCheck": "harness check",
|
|
327
|
+
"fromReport": "from the report",
|
|
328
|
+
"harnessNote": "_Harness tests — from the report; base — branch {branch} (source {source}{gap})._",
|
|
329
|
+
"harnessGap": " older than the diff base {sha}: the lists may contain tests of PRs merged between them",
|
|
330
|
+
"noSpecBase": "_Harness tests: branch {branch} has no tests.json for the base — a diff by sources, harness tests aren't visible in it._",
|
|
331
|
+
"partialReport": "⚠️ **Incomplete report:** it has no tests from {folders} whose names only a run knows — their tests weren't compared ({n} in branch {branch}) and aren't in «{removed}»; the full diff — with the report of a run of all tests.",
|
|
332
|
+
"modelModule": "module {module}",
|
|
333
|
+
"modelDependency": "dependency {from} → {to}",
|
|
334
|
+
"modelPackage": "package {package} of module {module}",
|
|
335
|
+
"registry": "registry",
|
|
336
|
+
"registryNamed": "registry «{value}»",
|
|
337
|
+
"rule": "rule",
|
|
338
|
+
"ruleNamed": "rule {value}",
|
|
339
|
+
"deadCode": "code without a consumer",
|
|
340
|
+
"deadCodeNamed": "code without a consumer ({value})",
|
|
341
|
+
"architecture": "architecture model",
|
|
342
|
+
"modelTitle": "Architecture model",
|
|
343
|
+
"exceptionsTitle": "Exceptions",
|
|
344
|
+
"checksTitle": "Harness checks",
|
|
345
|
+
"removedKind": "{title} — removed",
|
|
346
|
+
"addedKind": "{title} — added",
|
|
347
|
+
"summarized": "**{title} ({n}), as a summary:**"
|
|
348
|
+
},
|
|
349
|
+
"claims": {
|
|
350
|
+
"describe": "Every entry point is called by at least one capability test",
|
|
351
|
+
"registry": "entry points",
|
|
352
|
+
"unique": "entry-point ids do not repeat in the registry",
|
|
353
|
+
"called": "{entry} is called by a capability test",
|
|
354
|
+
"known": "ids from the log are in the registry"
|
|
355
|
+
},
|
|
356
|
+
"harness": {
|
|
357
|
+
"registryNotEmpty": "registry «{registry}» is not empty{tag}",
|
|
358
|
+
"registryFinds": "registry «{registry}» finds {items}{tag}",
|
|
359
|
+
"violator": "violator does not pass{tag}: {name}",
|
|
360
|
+
"oneRecord": "one record per element{tag}",
|
|
361
|
+
"markOneElement": "a mark belongs in one element's file{tag}",
|
|
362
|
+
"elementFiles": "element files from fileOf exist{tag}",
|
|
363
|
+
"outside": "outside scope{tag}: {item}",
|
|
364
|
+
"exception": "exception{tag}: {item} (#{issue})",
|
|
365
|
+
"exceptionFiles": "exceptions are one file per element in exceptions/, not exceptions.ts",
|
|
366
|
+
"exceptionJson": "exceptions are <element>.json files in the decision folder's exceptions/",
|
|
367
|
+
"exceptionRules": "exceptions with a rule belong to the folder's invariant rules",
|
|
368
|
+
"markRules": "marks with a rule belong to the folder's invariant rules",
|
|
369
|
+
"badExample": "rule {rule} has a «not allowed» example",
|
|
370
|
+
"bad": "not allowed",
|
|
371
|
+
"good": "allowed",
|
|
372
|
+
"outsideExample": "outside scope",
|
|
373
|
+
"codeFiles": "there are code files in {dirs}",
|
|
374
|
+
"lintExceptions": "exceptions in {file}: {rules}{issues}",
|
|
375
|
+
"knip": {
|
|
376
|
+
"files": "no files without a consumer",
|
|
377
|
+
"exports": "no exports without a consumer",
|
|
378
|
+
"types": "no types without a consumer",
|
|
379
|
+
"dependencies": "no dependencies without an import",
|
|
380
|
+
"unlisted": "no imports of unlisted packages",
|
|
381
|
+
"unresolved": "no unresolved imports",
|
|
382
|
+
"enumMembers": "no enum members without a consumer",
|
|
383
|
+
"nsMembers": "no namespace members without a consumer",
|
|
384
|
+
"duplicates": "no duplicate exports",
|
|
385
|
+
"binaries": "no calls to unlisted binaries",
|
|
386
|
+
"catalog": "no unused catalog entries",
|
|
387
|
+
"catalogReferences": "no references to missing catalog entries",
|
|
388
|
+
"known": "all knip findings are of known kinds{tag}",
|
|
389
|
+
"hints": "no knip configuration hints{tag}"
|
|
390
|
+
},
|
|
391
|
+
"ignoreNoReason": "outside scope without a reason: {items}",
|
|
392
|
+
"env": {
|
|
393
|
+
"inCode": "environment variables in the code",
|
|
394
|
+
"declaredName": "{name} is declared",
|
|
395
|
+
"undeclared": "a variable without a declaration",
|
|
396
|
+
"declared": "declared environment variables",
|
|
397
|
+
"readName": "{name} is read in the code",
|
|
398
|
+
"unread": "declared and not read"
|
|
399
|
+
}
|
|
400
|
+
},
|
|
401
|
+
"architecture": {
|
|
402
|
+
"dirsRegistry": "code directories",
|
|
403
|
+
"dirName": "directory {dir} is in module {module}",
|
|
404
|
+
"dirViolator": "a directory outside the modules",
|
|
405
|
+
"workspaceRegistry": "workspace packages",
|
|
406
|
+
"workspaceName": "workspace package {path} is in the code roots",
|
|
407
|
+
"workspaceViolator": "a workspace package outside the roots",
|
|
408
|
+
"importsRegistry": "external packages of modules",
|
|
409
|
+
"importsName": "{module} imports {package}",
|
|
410
|
+
"importsViolator": "a package not allowed for the module",
|
|
411
|
+
"allowedRegistry": "allowed packages of the model",
|
|
412
|
+
"allowedName": "{module} uses allowed package {package}",
|
|
413
|
+
"allowedViolator": "an allowed package without an import",
|
|
414
|
+
"containersRegistry": "modules in containers",
|
|
415
|
+
"libraryName": "library {module} is in containers {containers}",
|
|
416
|
+
"moduleName": "module {module} is in container {container}",
|
|
417
|
+
"containersViolator": "a module outside the containers",
|
|
418
|
+
"edgesRegistry": "module dependencies",
|
|
419
|
+
"edgeName": "dependency {from} → {to} is within a container",
|
|
420
|
+
"edgeViolator": "a dependency across containers",
|
|
421
|
+
"unitsRegistry": "deployable units",
|
|
422
|
+
"unitName": "deployable unit {unit} is container {container}",
|
|
423
|
+
"unitViolator": "a unit outside the model",
|
|
424
|
+
"clientsRegistry": "storage clients in containers",
|
|
425
|
+
"clientName": "client {package} of storage {storage} is in container {container}",
|
|
426
|
+
"clientViolator": "a client without a link",
|
|
427
|
+
"hostsRegistry": "hosts of external systems",
|
|
428
|
+
"hostName": "host {host} is only in {adapters}",
|
|
429
|
+
"hostPerimeter": "host {host} of external system {system} isn't in the code: no adapter",
|
|
430
|
+
"hostViolator": "a host outside the model",
|
|
431
|
+
"inAdapter": "adapter {list}",
|
|
432
|
+
"inAdapters": "adapters {list}",
|
|
433
|
+
"packagesRegistry": "packages of external systems",
|
|
434
|
+
"packageName": "package {package} of external system {system} is only with {adapters}",
|
|
435
|
+
"packagePerimeter": "package {package} of external system {system} is with no module: no adapter",
|
|
436
|
+
"packageViolator": "a package without an adapter",
|
|
437
|
+
"withAdapter": "adapter {list}",
|
|
438
|
+
"withAdapters": "adapters {list}",
|
|
439
|
+
"envRegistry": "environment keys of external systems",
|
|
440
|
+
"envNoun": "key",
|
|
441
|
+
"headersRegistry": "headers of external systems",
|
|
442
|
+
"headerNoun": "header",
|
|
443
|
+
"readName": "{noun} {key} of external system {system} is read only by adapter {list}",
|
|
444
|
+
"readNameMany": "{noun} {key} of external system {system} is read only by adapters {list}",
|
|
445
|
+
"readPerimeter": "{noun} {key} of external system {system} isn't in the code: no adapter",
|
|
446
|
+
"readViolator": "{noun} outside the adapter"
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
}
|