copilot-operator 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/LICENSE +21 -0
- package/README.md +556 -0
- package/dist/src/api/app.module.js +18 -0
- package/dist/src/api/dataAcl.js +109 -0
- package/dist/src/api/folderPicker.js +110 -0
- package/dist/src/api/main.js +132 -0
- package/dist/src/api/operator.controller.js +975 -0
- package/dist/src/api/operator.service.js +1971 -0
- package/dist/src/api/saveToDesktop.js +157 -0
- package/dist/src/api/security.js +225 -0
- package/dist/src/api/settings.js +57 -0
- package/dist/src/cli.js +531 -0
- package/dist/src/config/layout.js +66 -0
- package/dist/src/config/lockedPolicy.js +176 -0
- package/dist/src/config/schema.js +487 -0
- package/dist/src/context/contextFiles.js +295 -0
- package/dist/src/context/desktopMirror.js +113 -0
- package/dist/src/context/projectMirror.js +364 -0
- package/dist/src/exec/authorizer.js +61 -0
- package/dist/src/exec/checks.js +285 -0
- package/dist/src/exec/confinement.js +224 -0
- package/dist/src/exec/dangerous.js +161 -0
- package/dist/src/exec/environment.js +80 -0
- package/dist/src/exec/isolation.js +166 -0
- package/dist/src/exec/network.js +242 -0
- package/dist/src/exec/policy.js +201 -0
- package/dist/src/exec/policyManifest.js +84 -0
- package/dist/src/exec/processes.js +329 -0
- package/dist/src/exec/programs.js +290 -0
- package/dist/src/exec/redaction.js +93 -0
- package/dist/src/exec/reportFile.js +154 -0
- package/dist/src/exec/runner.js +245 -0
- package/dist/src/exec/scriptFiles.js +81 -0
- package/dist/src/exec/shellExecuteTrap.js +221 -0
- package/dist/src/exec/shells.js +298 -0
- package/dist/src/exec/stepEnv.js +72 -0
- package/dist/src/exec/winps.js +17 -0
- package/dist/src/exec/workDir.js +94 -0
- package/dist/src/log/runLog.js +43 -0
- package/dist/src/orchestrator/derivedChecks.js +95 -0
- package/dist/src/orchestrator/review.js +590 -0
- package/dist/src/orchestrator/taskRunner.js +1582 -0
- package/dist/src/plan/brief.js +1785 -0
- package/dist/src/plan/importPlan.js +202 -0
- package/dist/src/plan/schema.js +483 -0
- package/dist/src/plan/script.js +1012 -0
- package/dist/src/plan/systemGuide.js +1851 -0
- package/dist/src/protocol/parser.js +224 -0
- package/dist/src/protocol/replySchema.js +207 -0
- package/dist/src/protocol/reporter.js +75 -0
- package/dist/src/protocol/reviewSchema.js +205 -0
- package/dist/src/session/compose.js +67 -0
- package/dist/src/session/debugExport.js +165 -0
- package/dist/src/session/events.js +34 -0
- package/dist/src/session/exportRecord.js +261 -0
- package/dist/src/session/exports.js +484 -0
- package/dist/src/session/model.js +22 -0
- package/dist/src/session/retention.js +34 -0
- package/dist/src/session/runName.js +36 -0
- package/dist/src/session/store.js +440 -0
- package/dist/src/session/story.js +198 -0
- package/dist/src/transport/acceptance.js +34 -0
- package/dist/src/transport/chatSession.js +73 -0
- package/dist/src/transport/copilotTransport.js +1208 -0
- package/dist/src/transport/edgeCrash.js +59 -0
- package/dist/src/transport/locators.js +261 -0
- package/dist/src/transport/profileLock.js +102 -0
- package/dist/src/util/pacing.js +89 -0
- package/dist/src/vcs/commitHygiene.js +102 -0
- package/dist/src/vcs/git.js +286 -0
- package/dist/src/vcs/taskVcs.js +343 -0
- package/dist/web/404.html +15 -0
- package/dist/web/_next/static/chunks/12.f1f4d35b52633e8d.js +1 -0
- package/dist/web/_next/static/chunks/131-bae98f790a541679.js +1 -0
- package/dist/web/_next/static/chunks/197-f7c33a0114fc3db3.js +1 -0
- package/dist/web/_next/static/chunks/489.158bbe303a595fba.js +1 -0
- package/dist/web/_next/static/chunks/643-34b9f66a6c317c4a.js +1 -0
- package/dist/web/_next/static/chunks/867-03b7cac8f79896c3.js +1 -0
- package/dist/web/_next/static/chunks/955-63de06e182d98949.js +1 -0
- package/dist/web/_next/static/chunks/app/_not-found/page-0d0d8e7e62efca12.js +1 -0
- package/dist/web/_next/static/chunks/app/appearance/page-501842e7aeac7f6b.js +1 -0
- package/dist/web/_next/static/chunks/app/defaults/page-ed858127cbdfb4ab.js +1 -0
- package/dist/web/_next/static/chunks/app/history/page-bad4f3e89b485719.js +1 -0
- package/dist/web/_next/static/chunks/app/import/page-db1f5f1ab2f5cad1.js +1 -0
- package/dist/web/_next/static/chunks/app/layout-72251c52cc54f95e.js +1 -0
- package/dist/web/_next/static/chunks/app/level1/page-cf3e50cf64fecf4f.js +1 -0
- package/dist/web/_next/static/chunks/app/page-6fd16e5c8cf3b20f.js +1 -0
- package/dist/web/_next/static/chunks/app/presets/page-951e78b80e0e22e6.js +1 -0
- package/dist/web/_next/static/chunks/app/sessions/view/page-f2e63618097d7221.js +1 -0
- package/dist/web/_next/static/chunks/app/system/page-44e7954c0e48f4ba.js +1 -0
- package/dist/web/_next/static/chunks/c7879cf7-b5ab1053c1d9a2e7.js +1 -0
- package/dist/web/_next/static/chunks/framework-9ac6a346bd42cedd.js +1 -0
- package/dist/web/_next/static/chunks/main-6be4444e2d667e41.js +1 -0
- package/dist/web/_next/static/chunks/main-app-e3a5f713ba31557e.js +1 -0
- package/dist/web/_next/static/chunks/pages/_app-32d20d5a04949d29.js +1 -0
- package/dist/web/_next/static/chunks/pages/_error-abbab53f25ea29b0.js +1 -0
- package/dist/web/_next/static/chunks/polyfills-42372ed130431b0a.js +1 -0
- package/dist/web/_next/static/chunks/webpack-0f31b926d9a9c5a4.js +1 -0
- package/dist/web/_next/static/css/d77735cdc9020a86.css +1 -0
- package/dist/web/_next/static/u8rZNwh4d3n-HGJnfZ72Y/_buildManifest.js +1 -0
- package/dist/web/_next/static/u8rZNwh4d3n-HGJnfZ72Y/_ssgManifest.js +1 -0
- package/dist/web/appearance.html +15 -0
- package/dist/web/appearance.txt +26 -0
- package/dist/web/defaults.html +15 -0
- package/dist/web/defaults.txt +26 -0
- package/dist/web/history.html +15 -0
- package/dist/web/history.txt +26 -0
- package/dist/web/import.html +15 -0
- package/dist/web/import.txt +26 -0
- package/dist/web/index.html +15 -0
- package/dist/web/index.txt +26 -0
- package/dist/web/level1.html +15 -0
- package/dist/web/level1.txt +26 -0
- package/dist/web/presets.html +18 -0
- package/dist/web/presets.txt +26 -0
- package/dist/web/sessions/view.html +15 -0
- package/dist/web/sessions/view.txt +26 -0
- package/dist/web/system.html +15 -0
- package/dist/web/system.txt +26 -0
- package/package.json +111 -0
- package/prompts/level1.md +535 -0
- package/prompts/organisation.bg.md +44 -0
- package/prompts/organisation.en.md +44 -0
- package/prompts/persona.bg.md +17 -0
- package/prompts/persona.en.md +17 -0
- package/prompts/review1.md +277 -0
- package/prompts/work.bg.md +19 -0
- package/prompts/work.en.md +19 -0
|
@@ -0,0 +1,1012 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The phase lines, fixed. Left to the model it copied whatever heading was nearest — "Фаза 0 — още
|
|
3
|
+
* нищо не е записано, затова направи това преди всичко останало" is the brief's own section title —
|
|
4
|
+
* and named the same phase three ways in one conversation.
|
|
5
|
+
*/
|
|
6
|
+
export const PHASE_LINES = {
|
|
7
|
+
p0: { en: 'Phase 0 — how work is done here', bg: 'Фаза 0 — как се работи тук' },
|
|
8
|
+
beforeP1: { en: 'Before phase 1 — the approach', bg: 'Преди фаза 1 — подходът' },
|
|
9
|
+
p1: { en: 'Phase 1 — this work', bg: 'Фаза 1 — тази работа' },
|
|
10
|
+
p2: { en: 'Phase 2 — the plan and the run', bg: 'Фаза 2 — планът и пускането' },
|
|
11
|
+
p3: { en: 'Phase 3 — why it did not end done', bg: 'Фаза 3 — защо не завърши готова' },
|
|
12
|
+
p4: { en: 'Phase 4 — the verdict', bg: 'Фаза 4 — присъдата' },
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* The marker for an answer the model already has, and the two ways a message carrying one ends.
|
|
16
|
+
*
|
|
17
|
+
* "On record" alone read as a statement, and the operator asked where it came from and why it was
|
|
18
|
+
* being asked again: the answer is that it came from their own documents or an earlier answer in
|
|
19
|
+
* this conversation, and it is shown so they can correct it. The marker now says that in its own
|
|
20
|
+
* words. A message could also carry both answered and unanswered questions, and with only one fixed
|
|
21
|
+
* ending for the all-answered case the model wrote its own for the mixed one.
|
|
22
|
+
*/
|
|
23
|
+
export const ALREADY_SAID = {
|
|
24
|
+
en: 'Already said — confirm or correct:',
|
|
25
|
+
bg: 'Вече казано — потвърди или поправи:',
|
|
26
|
+
};
|
|
27
|
+
export const ON_RECORD_ALL = {
|
|
28
|
+
en: 'If everything already said is right, answer `right`; otherwise write only the numbers you change, with the new answer.',
|
|
29
|
+
bg: 'Ако всичко казано е вярно, отговори `вярно`; иначе напиши само номерата, които променяш, с новия отговор.',
|
|
30
|
+
};
|
|
31
|
+
export const ON_RECORD_MIXED = {
|
|
32
|
+
en: 'Answer under the numbers without "Already said"; where what is already said is right, write nothing under it, otherwise correct it under its number.',
|
|
33
|
+
bg: 'Отговори под номерата без „Вече казано“; където казаното е вярно, не пиши нищо под него, иначе го поправи под номера му.',
|
|
34
|
+
};
|
|
35
|
+
const OTHER = { en: 'something else — say what', bg: 'друго — напиши какво' };
|
|
36
|
+
const OTHER_FOLDER = { en: 'another folder — give its absolute path', bg: 'друга папка — напиши абсолютния ѝ път' };
|
|
37
|
+
const OTHER_RULE = { en: 'something else — write the rule and an example', bg: 'друго — напиши правилото и пример' };
|
|
38
|
+
export const SCRIPT = [
|
|
39
|
+
{
|
|
40
|
+
id: 'org-work',
|
|
41
|
+
stages: ['phase0'],
|
|
42
|
+
phase: 'p0',
|
|
43
|
+
when: {
|
|
44
|
+
en: 'Phase 0, the first message: where work comes from and where information lives',
|
|
45
|
+
bg: 'Фаза 0, първото съобщение: откъде идва работата и къде е информацията',
|
|
46
|
+
},
|
|
47
|
+
questions: [
|
|
48
|
+
{
|
|
49
|
+
ask: {
|
|
50
|
+
en: 'Where does work come from: which ticket system do you use (Azure DevOps, Jira, GitHub, email or another), and what does a ticket always carry?',
|
|
51
|
+
bg: 'Откъде идва работата: коя система за ticket-и ползвате (Azure DevOps, Jira, GitHub, имейл или друга) и какво носи винаги един ticket?',
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
ask: {
|
|
56
|
+
en: 'What are the acceptance criteria called, and where are they written?',
|
|
57
|
+
bg: 'Как се наричат критериите за приемане и къде са записани?',
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
ask: {
|
|
62
|
+
en: 'Where does the information live that I may need (OneDrive, SharePoint, Teams, a wiki, a docs folder)? What may I search from this chat, and what must you give me?',
|
|
63
|
+
bg: 'Къде е информацията, която може да ми потрябва (OneDrive, SharePoint, Teams, wiki, папка с документи)? Кое мога да търся от този чат и кое трябва да ми дадеш?',
|
|
64
|
+
},
|
|
65
|
+
},
|
|
66
|
+
{
|
|
67
|
+
choose: {
|
|
68
|
+
en: 'Which of the projects on this machine do we describe? Several are fine.',
|
|
69
|
+
bg: 'Кои от проектите на тази машина да опишем? Може няколко.',
|
|
70
|
+
},
|
|
71
|
+
options: 'projects',
|
|
72
|
+
},
|
|
73
|
+
],
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
id: 'org-project',
|
|
77
|
+
stages: ['phase0'],
|
|
78
|
+
phase: 'p0',
|
|
79
|
+
when: {
|
|
80
|
+
en: 'Phase 0: one message for each project picked in the first message, with its path in {path}',
|
|
81
|
+
bg: 'Фаза 0: по едно съобщение за всеки проект, избран в първото съобщение, с пътя му в {път}',
|
|
82
|
+
},
|
|
83
|
+
lead: [{ en: 'Project `{path}`:', bg: 'Проект `{път}`:' }],
|
|
84
|
+
questions: [
|
|
85
|
+
{
|
|
86
|
+
ask: { en: 'What does this project do, in one sentence?', bg: 'Какво прави този проект, с едно изречение?' },
|
|
87
|
+
hints: [
|
|
88
|
+
{
|
|
89
|
+
en: 'Example: an orders REST API on Node.js; a Next.js website; Playwright tests for the web application; a .NET library.',
|
|
90
|
+
bg: 'Пример: REST API за поръчки на Node.js; сайт на Next.js; тестове на Playwright за уеб приложението; библиотека на .NET.',
|
|
91
|
+
},
|
|
92
|
+
],
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
ask: { en: 'Which folders in it matter, and what is in them?', bg: 'Кои папки в него имат значение и какво има в тях?' },
|
|
96
|
+
hints: [
|
|
97
|
+
{
|
|
98
|
+
en: 'Example: src — the code; test — the tests; migrations — the database changes; docs — the documentation.',
|
|
99
|
+
bg: 'Пример: src — кодът; test — тестовете; migrations — промените по базата; docs — документацията.',
|
|
100
|
+
},
|
|
101
|
+
],
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
ask: {
|
|
105
|
+
en: 'What must be installed, running or set before it builds and its tests run?',
|
|
106
|
+
bg: 'Какво трябва да е инсталирано, пуснато или зададено, преди да се строи и да се пуснат тестовете?',
|
|
107
|
+
},
|
|
108
|
+
hints: [
|
|
109
|
+
{
|
|
110
|
+
en: 'Easiest: attach or paste the files that already say it — README, package.json (the engines field), .nvmrc, Dockerfile, docker-compose.yml, `*.csproj` or global.json (.NET), pom.xml or build.gradle (Java), requirements.txt or pyproject.toml (Python), go.mod (Go).',
|
|
111
|
+
bg: 'Най-лесно: прикачи или постави файловете, които вече го казват — README, package.json (полето engines), .nvmrc, Dockerfile, docker-compose.yml, `*.csproj` или global.json (.NET), pom.xml или build.gradle (Java), requirements.txt или pyproject.toml (Python), go.mod (Go).',
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
en: 'Example: Node.js 20 and TypeScript 5; Playwright with the Chromium browser; the .NET 8 SDK; Java 17 and Maven; Python 3.12 and Poetry; Docker with the postgres:16 and redis:7 images; a Kubernetes cluster for the integration tests; the DATABASE_URL environment variable.',
|
|
115
|
+
bg: 'Пример: Node.js 20 и TypeScript 5; Playwright с браузъра Chromium; .NET 8 SDK; Java 17 и Maven; Python 3.12 и Poetry; Docker с образите postgres:16 и redis:7; Kubernetes клъстер за интеграционните тестове; променливата на средата DATABASE_URL.',
|
|
116
|
+
},
|
|
117
|
+
],
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
choose: { en: 'Which commands build, start and test it?', bg: 'С кои команди се строи, пуска и тества?' },
|
|
121
|
+
options: [
|
|
122
|
+
{
|
|
123
|
+
en: 'I will attach the file that defines them — package.json (scripts), Makefile, `*.csproj` or `*.sln`, pom.xml, build.gradle, pyproject.toml or tox.ini, justfile',
|
|
124
|
+
bg: 'Ще прикача файла, в който са описани — package.json (scripts), Makefile, `*.csproj` или `*.sln`, pom.xml, build.gradle, pyproject.toml или tox.ini, justfile',
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
en: 'I will write them here: which command builds, which starts and which tests',
|
|
128
|
+
bg: 'Ще ги напиша тук: коя команда строи, коя пуска и коя тества',
|
|
129
|
+
},
|
|
130
|
+
],
|
|
131
|
+
other: false,
|
|
132
|
+
recommend: false,
|
|
133
|
+
hints: [
|
|
134
|
+
{
|
|
135
|
+
en: 'Example: npm run build, npm start, npm test; dotnet build, dotnet test; mvn package, mvn test; pytest; go test ./...',
|
|
136
|
+
bg: 'Пример: npm run build, npm start, npm test; dotnet build, dotnet test; mvn package, mvn test; pytest; go test ./...',
|
|
137
|
+
},
|
|
138
|
+
],
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
choose: {
|
|
142
|
+
en: 'What traps are there — things not visible in the code that break the build, the start or the tests? Several are fine.',
|
|
143
|
+
bg: 'Какви капани има тук — неща, които не личат от кода, но чупят build-а, пускането или тестовете? Може няколко.',
|
|
144
|
+
},
|
|
145
|
+
options: [
|
|
146
|
+
{ en: 'None that I know of', bg: 'Не знам за такива' },
|
|
147
|
+
{
|
|
148
|
+
en: 'A service must be running separately — a database, a queue, another service (say which and how it starts)',
|
|
149
|
+
bg: 'Трябва услуга, пусната отделно — база, опашка, друг сървис (напиши коя и как се пуска)',
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
en: 'A command that looks right but does not work (say which, and what is used instead)',
|
|
153
|
+
bg: 'Команда, която изглежда вярна, но не работи (напиши коя и какво се ползва вместо нея)',
|
|
154
|
+
},
|
|
155
|
+
{
|
|
156
|
+
en: 'Tests that depend on order, time, the network or data (say which)',
|
|
157
|
+
bg: 'Тестове, които зависят от ред, време, мрежа или данни (напиши кои)',
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
en: 'A cache or generated files that must be cleared (say which and how)',
|
|
161
|
+
bg: 'Кеш или генерирани файлове, които трябва да се изчистят (напиши кои и как)',
|
|
162
|
+
},
|
|
163
|
+
],
|
|
164
|
+
recommend: false,
|
|
165
|
+
hints: [
|
|
166
|
+
{
|
|
167
|
+
en: 'This is the knowledge a person gathers the hard way, and it is worth the most of anything here.',
|
|
168
|
+
bg: 'Това е знанието, което човек събира по трудния начин, и то струва най-много от всичко тук.',
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
en: 'Example: "npm test does not work, the tests run with …"; "port 3000 is taken by another application"; "after a schema change a migration must be run".',
|
|
172
|
+
bg: 'Пример: „npm test не работи, тестовете се пускат с …“; „портът 3000 е зает от друго приложение“; „след смяна на схемата трябва да се пусне миграция“.',
|
|
173
|
+
},
|
|
174
|
+
],
|
|
175
|
+
},
|
|
176
|
+
{
|
|
177
|
+
choose: { en: 'How do I read its code from this chat?', bg: 'Как да чета кода му от този чат?' },
|
|
178
|
+
options: [
|
|
179
|
+
{ en: 'As files attached to the first message of a task', bg: 'Като прикачени файлове към първото съобщение на задачата' },
|
|
180
|
+
{ en: 'Through the Desktop mirror (Desktop/copilot-operator-context/)', bg: 'През огледалото на Desktop-а (Desktop/copilot-operator-context/)' },
|
|
181
|
+
{ en: 'Both', bg: 'И двете' },
|
|
182
|
+
],
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
choose: {
|
|
186
|
+
en: 'May the bot make git branches and commits in this project?',
|
|
187
|
+
bg: 'Може ли ботът да прави git клонове и комити в този проект?',
|
|
188
|
+
},
|
|
189
|
+
options: [
|
|
190
|
+
{ en: 'Yes — a branch before each task and a commit after it, never a push', bg: 'Да — клон преди всяка задача и комит след нея, без push' },
|
|
191
|
+
{ en: 'No — files change in place, with no git', bg: 'Не — файловете се променят на място, без git' },
|
|
192
|
+
],
|
|
193
|
+
recommend: false,
|
|
194
|
+
hints: [
|
|
195
|
+
{
|
|
196
|
+
en: 'With yes, there is always a way back to the code as it was before a task. With no, files change directly, with no history and no way back.',
|
|
197
|
+
bg: 'При „Да“ винаги има връщане към кода отпреди задачата. При „Не“ файловете се променят направо, без история и без връщане назад.',
|
|
198
|
+
},
|
|
199
|
+
],
|
|
200
|
+
},
|
|
201
|
+
],
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
id: 'org-conventions',
|
|
205
|
+
stages: ['phase0'],
|
|
206
|
+
phase: 'p0',
|
|
207
|
+
when: { en: 'Phase 0: the conventions', bg: 'Фаза 0: правилата' },
|
|
208
|
+
questions: [
|
|
209
|
+
{
|
|
210
|
+
choose: { en: 'How are git branches named?', bg: 'Как се именуват git клоновете?' },
|
|
211
|
+
options: [
|
|
212
|
+
{ en: '`feature/<ticket>-<description>` — for example feature/PBI-123-login-page', bg: '`feature/<ticket>-<описание>` — например feature/PBI-123-login-page' },
|
|
213
|
+
{ en: '`<type>/<description>` — for example fix/null-id, chore/update-deps', bg: '`<тип>/<описание>` — например fix/null-id, chore/update-deps' },
|
|
214
|
+
{ en: "`cop/<short-name>` — the bot's own prefix, for example cop/calculator-core", bg: '`cop/<кратко-име>` — префиксът на бота, например cop/calculator-core' },
|
|
215
|
+
{ en: 'No rule', bg: 'Няма правило' },
|
|
216
|
+
],
|
|
217
|
+
other: OTHER_RULE,
|
|
218
|
+
recommend: false,
|
|
219
|
+
},
|
|
220
|
+
{
|
|
221
|
+
choose: { en: 'What is the commit message style?', bg: 'Какъв е стилът на комит съобщенията?' },
|
|
222
|
+
options: [
|
|
223
|
+
{ en: 'Conventional Commits — for example `feat: add login page`, `fix(api): handle a missing id`', bg: 'Conventional Commits — например `feat: add login page`, `fix(api): handle a missing id`' },
|
|
224
|
+
{ en: 'The ticket number first — for example `PBI-123 Add login page`', bg: 'Номерът на ticket-а отпред — например `PBI-123 Add login page`' },
|
|
225
|
+
{ en: 'One sentence in the imperative — for example `Add login page`', bg: 'Едно изречение в повелително наклонение — например `Add login page`' },
|
|
226
|
+
{ en: 'No rule', bg: 'Няма правило' },
|
|
227
|
+
],
|
|
228
|
+
other: OTHER_RULE,
|
|
229
|
+
recommend: false,
|
|
230
|
+
},
|
|
231
|
+
{
|
|
232
|
+
choose: { en: 'How does a change reach the main branch?', bg: 'Как промяната стига до основния клон?' },
|
|
233
|
+
options: [
|
|
234
|
+
{ en: 'No pull requests — the work stays local on its branches', bg: 'Без pull request-и — работата остава локално в клоновете си' },
|
|
235
|
+
{
|
|
236
|
+
en: 'A pull request on GitHub, Azure DevOps or GitLab, with an approval and a green CI — say who approves and which checks',
|
|
237
|
+
bg: 'Pull request в GitHub, Azure DevOps или GitLab, с одобрение и зелен CI — напиши кой одобрява и кои проверки',
|
|
238
|
+
},
|
|
239
|
+
],
|
|
240
|
+
recommend: false,
|
|
241
|
+
hints: [
|
|
242
|
+
{
|
|
243
|
+
en: 'That is: is there a pull request, who approves it, and which checks must pass before the merge.',
|
|
244
|
+
bg: 'Тоест: има ли pull request, кой го одобрява и кои проверки трябва да минат преди merge.',
|
|
245
|
+
},
|
|
246
|
+
],
|
|
247
|
+
},
|
|
248
|
+
{
|
|
249
|
+
ask: {
|
|
250
|
+
en: 'Which command runs the tests, and is there a coverage threshold?',
|
|
251
|
+
bg: 'С коя команда се пускат тестовете и има ли праг за покритие?',
|
|
252
|
+
},
|
|
253
|
+
hints: [
|
|
254
|
+
{
|
|
255
|
+
en: 'Example: npm test; npx playwright test; dotnet test; mvn test; gradle test; pytest; go test ./... — coverage at least 80%.',
|
|
256
|
+
bg: 'Пример: npm test; npx playwright test; dotnet test; mvn test; gradle test; pytest; go test ./... — покритие поне 80%.',
|
|
257
|
+
},
|
|
258
|
+
],
|
|
259
|
+
},
|
|
260
|
+
{
|
|
261
|
+
ask: {
|
|
262
|
+
en: 'What are the coding standards: language version, linter, formatter?',
|
|
263
|
+
bg: 'Какви са стандартите за код: версия на езика, линтер, форматер?',
|
|
264
|
+
},
|
|
265
|
+
hints: [
|
|
266
|
+
{
|
|
267
|
+
en: 'You may attach their configuration instead: .eslintrc, .prettierrc, .editorconfig, tsconfig.json, pyproject.toml, checkstyle.xml.',
|
|
268
|
+
bg: 'Може вместо това да прикачиш конфигурацията им: .eslintrc, .prettierrc, .editorconfig, tsconfig.json, pyproject.toml, checkstyle.xml.',
|
|
269
|
+
},
|
|
270
|
+
{
|
|
271
|
+
en: 'Example: TypeScript 5 in strict mode with ESLint and Prettier; C# 12 with .editorconfig and dotnet format; Java 17 with Checkstyle; Python 3.12 with ruff and black; Go with gofmt.',
|
|
272
|
+
bg: 'Пример: TypeScript 5 в strict режим с ESLint и Prettier; C# 12 с .editorconfig и dotnet format; Java 17 с Checkstyle; Python 3.12 с ruff и black; Go с gofmt.',
|
|
273
|
+
},
|
|
274
|
+
],
|
|
275
|
+
},
|
|
276
|
+
{
|
|
277
|
+
ask: { en: 'How are files and folders named?', bg: 'Как се именуват файловете и папките?' },
|
|
278
|
+
hints: [
|
|
279
|
+
{
|
|
280
|
+
en: 'Example: files in kebab-case (user-service.ts); classes in PascalCase (UserService.cs); tests beside the code as .test.ts or .spec.ts, or in a tests folder; Java packages as com.company.module.',
|
|
281
|
+
bg: 'Пример: файловете в kebab-case (user-service.ts); класовете в PascalCase (UserService.cs); тестовете до кода като .test.ts или .spec.ts, или в папка tests; пакетите в Java — com.company.module.',
|
|
282
|
+
},
|
|
283
|
+
],
|
|
284
|
+
},
|
|
285
|
+
{
|
|
286
|
+
choose: {
|
|
287
|
+
en: 'Are there templates or scaffolds new code starts from?',
|
|
288
|
+
bg: 'Има ли шаблони или скелети, от които тръгва новият код?',
|
|
289
|
+
},
|
|
290
|
+
options: [
|
|
291
|
+
{ en: 'No', bg: 'Няма' },
|
|
292
|
+
{
|
|
293
|
+
en: 'Yes — say where: a folder, a repository or a generator (`dotnet new`, `npm create`, Spring Initializr, cookiecutter)',
|
|
294
|
+
bg: 'Да — напиши къде: папка, хранилище или генератор (`dotnet new`, `npm create`, Spring Initializr, cookiecutter)',
|
|
295
|
+
},
|
|
296
|
+
],
|
|
297
|
+
recommend: false,
|
|
298
|
+
hints: [
|
|
299
|
+
{
|
|
300
|
+
en: 'That is: a ready sample project, a generator or a folder of examples that new code must follow.',
|
|
301
|
+
bg: 'Тоест: готов примерен проект, генератор или папка с образци, които новият код трябва да следва.',
|
|
302
|
+
},
|
|
303
|
+
],
|
|
304
|
+
},
|
|
305
|
+
{
|
|
306
|
+
choose: {
|
|
307
|
+
en: 'When is a piece of work finished (definition of done)? Several are fine.',
|
|
308
|
+
bg: 'Кога една работа се смята за завършена (definition of done)? Може няколко.',
|
|
309
|
+
},
|
|
310
|
+
options: [
|
|
311
|
+
{ en: 'The build passes — npm run build, dotnet build, mvn package, gradle build', bg: 'Build-ът минава — npm run build, dotnet build, mvn package, gradle build' },
|
|
312
|
+
{ en: 'All tests pass — npm test, dotnet test, mvn test, pytest, go test ./...', bg: 'Всички тестове минават — npm test, dotnet test, mvn test, pytest, go test ./...' },
|
|
313
|
+
{ en: 'New behaviour is covered by a test', bg: 'Новото поведение е покрито с тест' },
|
|
314
|
+
{
|
|
315
|
+
en: 'The linter and formatter pass — eslint, prettier --check, dotnet format --verify-no-changes, ruff, gofmt',
|
|
316
|
+
bg: 'Линтерът и форматерът минават — eslint, prettier --check, dotnet format --verify-no-changes, ruff, gofmt',
|
|
317
|
+
},
|
|
318
|
+
{ en: 'Coverage does not drop below the threshold', bg: 'Покритието не пада под прага' },
|
|
319
|
+
{ en: 'The documentation is updated — README, CHANGELOG', bg: 'Документацията е обновена — README, CHANGELOG' },
|
|
320
|
+
],
|
|
321
|
+
recommend: false,
|
|
322
|
+
},
|
|
323
|
+
],
|
|
324
|
+
},
|
|
325
|
+
{
|
|
326
|
+
id: 'org-people',
|
|
327
|
+
stages: ['phase0'],
|
|
328
|
+
phase: 'p0',
|
|
329
|
+
when: { en: 'Phase 0: people and limits', bg: 'Фаза 0: хората и границите' },
|
|
330
|
+
questions: [
|
|
331
|
+
{
|
|
332
|
+
ask: {
|
|
333
|
+
en: "Which changes must not be made without somebody's agreement first — and whose?",
|
|
334
|
+
bg: 'Кои промени не бива да се правят без нечие предварително съгласие — и чие?',
|
|
335
|
+
},
|
|
336
|
+
hints: [
|
|
337
|
+
{
|
|
338
|
+
en: 'Example: a new external dependency — the tech lead; a database schema change — the architect; a change to the public API — the product owner.',
|
|
339
|
+
bg: 'Пример: нова външна зависимост — tech lead-ът; промяна в схемата на базата — архитектът; промяна в публичното API — продуктовият собственик.',
|
|
340
|
+
},
|
|
341
|
+
],
|
|
342
|
+
},
|
|
343
|
+
{
|
|
344
|
+
ask: {
|
|
345
|
+
en: 'Who accepts finished work — who does the code review or closes the ticket?',
|
|
346
|
+
bg: 'Кой приема завършената работа — кой прави code review или затваря ticket-а?',
|
|
347
|
+
},
|
|
348
|
+
hints: [
|
|
349
|
+
{
|
|
350
|
+
en: 'Example: every pull request is approved by one senior developer; QA closes the ticket after checking it on staging; nobody, for a test.',
|
|
351
|
+
bg: 'Пример: всеки pull request се одобрява от един senior; QA затваря ticket-а след проверка на staging; за тест — никой.',
|
|
352
|
+
},
|
|
353
|
+
],
|
|
354
|
+
},
|
|
355
|
+
{
|
|
356
|
+
ask: {
|
|
357
|
+
en: 'What must the bot never change — files, folders, settings?',
|
|
358
|
+
bg: 'Какво ботът никога не бива да променя — файлове, папки, настройки?',
|
|
359
|
+
},
|
|
360
|
+
hints: [
|
|
361
|
+
{
|
|
362
|
+
en: 'Example: .github/workflows and the rest of the CI; migrations already applied; package-lock.json; .env and the secrets; the infra folder; modules owned by another team.',
|
|
363
|
+
bg: 'Пример: .github/workflows и останалия CI; вече пуснати миграции; package-lock.json; .env и тайните; папката infra; модули на друг екип.',
|
|
364
|
+
},
|
|
365
|
+
],
|
|
366
|
+
},
|
|
367
|
+
],
|
|
368
|
+
},
|
|
369
|
+
{
|
|
370
|
+
id: 'persona-ask',
|
|
371
|
+
stages: ['phase0', 'persona'],
|
|
372
|
+
phase: 'persona',
|
|
373
|
+
when: {
|
|
374
|
+
en: 'The persona: in phase 0 after "people and limits"; before phase 1 as the first message',
|
|
375
|
+
bg: 'Персоната: във фаза 0 след „хората и границите“; преди фаза 1 — като първо съобщение',
|
|
376
|
+
},
|
|
377
|
+
questions: [
|
|
378
|
+
{
|
|
379
|
+
choose: { en: 'How will the tasks be carried out?', bg: 'Как ще се изпълняват задачите?' },
|
|
380
|
+
options: [
|
|
381
|
+
{
|
|
382
|
+
en: 'I have a persona and will give it to you in my next chat message, for you to validate.',
|
|
383
|
+
bg: 'Имам персона и ще я предоставя в следващото си чат съобщение, за да я валидираш.',
|
|
384
|
+
},
|
|
385
|
+
{
|
|
386
|
+
en: 'I do not have a persona and want you to help me create it.',
|
|
387
|
+
bg: 'Нямам персона и искам да ми помогнеш да я създадем.',
|
|
388
|
+
},
|
|
389
|
+
],
|
|
390
|
+
other: false,
|
|
391
|
+
recommend: false,
|
|
392
|
+
},
|
|
393
|
+
],
|
|
394
|
+
},
|
|
395
|
+
{
|
|
396
|
+
id: 'persona-validate',
|
|
397
|
+
stages: ['phase0', 'persona'],
|
|
398
|
+
phase: 'persona',
|
|
399
|
+
when: {
|
|
400
|
+
en: 'The persona, answer 1: once the operator has sent it. Fill each {…} with "clear" or with what is missing',
|
|
401
|
+
bg: 'Персоната, отговор 1: щом операторът я прати. Всяко {…} е „ясно“ или какво липсва',
|
|
402
|
+
},
|
|
403
|
+
lead: [
|
|
404
|
+
{ en: 'I checked the persona for the five things it must make clear:', bg: 'Проверих персоната за петте неща, които трябва да са ясни:' },
|
|
405
|
+
{ en: '- What the agent is responsible for, and what not: {…}', bg: '- За какво отговаря агентът и за какво не: {…}' },
|
|
406
|
+
{ en: '- Its approach: {…}', bg: '- Подходът му: {…}' },
|
|
407
|
+
{ en: '- Its phases, and what shows each is done: {…}', bg: '- Фазите му и какво показва, че всяка е свършена: {…}' },
|
|
408
|
+
{ en: '- The result it hands back: {…}', bg: '- Резултатът, който предава: {…}' },
|
|
409
|
+
{ en: '- No name, not written as a character: {…}', bg: '- Без име и не е написана като герой: {…}' },
|
|
410
|
+
],
|
|
411
|
+
questions: [
|
|
412
|
+
{
|
|
413
|
+
choose: { en: 'What do we do?', bg: 'Какво правим?' },
|
|
414
|
+
options: [
|
|
415
|
+
{ en: 'I will fix it and send it again in my next message.', bg: 'Ще я поправя и ще я пратя пак в следващото си съобщение.' },
|
|
416
|
+
{ en: 'We go on with it as it is.', bg: 'Продължаваме с нея, както е.' },
|
|
417
|
+
],
|
|
418
|
+
},
|
|
419
|
+
],
|
|
420
|
+
},
|
|
421
|
+
{
|
|
422
|
+
id: 'persona-build-approach',
|
|
423
|
+
stages: ['phase0', 'persona'],
|
|
424
|
+
phase: 'persona',
|
|
425
|
+
when: {
|
|
426
|
+
en: 'The persona, answer 2, first message: responsibilities and approach',
|
|
427
|
+
bg: 'Персоната, отговор 2, първо съобщение: отговорностите и подходът',
|
|
428
|
+
},
|
|
429
|
+
questions: [
|
|
430
|
+
{
|
|
431
|
+
choose: {
|
|
432
|
+
en: 'What is the agent responsible for in this work? Several are fine.',
|
|
433
|
+
bg: 'За какво отговаря агентът в тази работа? Може няколко.',
|
|
434
|
+
},
|
|
435
|
+
options: [
|
|
436
|
+
{ en: 'Writes new code and the tests for it', bg: 'Пише нов код и тестовете за него' },
|
|
437
|
+
{ en: 'Fixes bugs and proves each fix with a test', bg: 'Поправя бъгове и доказва всяка поправка с тест' },
|
|
438
|
+
{
|
|
439
|
+
en: 'Writes automated tests for existing code — unit, integration, end-to-end (for example Playwright)',
|
|
440
|
+
bg: 'Пише автоматизирани тестове за съществуващ код — unit, интеграционни, end-to-end (например Playwright)',
|
|
441
|
+
},
|
|
442
|
+
{ en: 'Refactors without changing behaviour', bg: 'Рефакторира, без да променя поведението' },
|
|
443
|
+
{ en: 'Audits or reviews — only reads and reports', bg: 'Прави одит или преглед — само чете и докладва' },
|
|
444
|
+
],
|
|
445
|
+
recommend: false,
|
|
446
|
+
},
|
|
447
|
+
{
|
|
448
|
+
choose: {
|
|
449
|
+
en: 'What is it NOT responsible for — what does it leave to somebody else? Several are fine.',
|
|
450
|
+
bg: 'За какво НЕ отговаря — какво оставя на някой друг? Може няколко.',
|
|
451
|
+
},
|
|
452
|
+
options: [
|
|
453
|
+
{ en: 'Deploying and releasing', bg: 'Deploy и release' },
|
|
454
|
+
{ en: 'Anything outside the project folder', bg: 'Нищо извън папката на проекта' },
|
|
455
|
+
{ en: 'New external dependencies', bg: 'Нови външни зависимости' },
|
|
456
|
+
{ en: 'CI/CD and infrastructure', bg: 'CI/CD и инфраструктурата' },
|
|
457
|
+
{ en: 'The database schema and migrations', bg: 'Схемата на базата и миграциите' },
|
|
458
|
+
],
|
|
459
|
+
recommend: false,
|
|
460
|
+
},
|
|
461
|
+
{
|
|
462
|
+
choose: { en: 'Pace:', bg: 'Темпо:' },
|
|
463
|
+
options: [
|
|
464
|
+
{
|
|
465
|
+
en: 'Cautious — proves every claim with a command before making it',
|
|
466
|
+
bg: 'Предпазливо — доказва всяко твърдение с команда, преди да го направи',
|
|
467
|
+
},
|
|
468
|
+
{ en: 'Quick — verifies only at the end', bg: 'Бързо — проверява само накрая' },
|
|
469
|
+
],
|
|
470
|
+
},
|
|
471
|
+
{
|
|
472
|
+
choose: { en: 'Code:', bg: 'Код:' },
|
|
473
|
+
options: [
|
|
474
|
+
{ en: 'May change code', bg: 'Може да променя код' },
|
|
475
|
+
{ en: 'Only reads code and reports', bg: 'Само чете код и докладва' },
|
|
476
|
+
],
|
|
477
|
+
},
|
|
478
|
+
{
|
|
479
|
+
choose: {
|
|
480
|
+
en: 'When does it stop and report rather than guess? Several are fine.',
|
|
481
|
+
bg: 'Кога спира и докладва, вместо да гадае? Може няколко.',
|
|
482
|
+
},
|
|
483
|
+
options: [
|
|
484
|
+
{ en: 'When the assignment is unclear or contradicts itself', bg: 'Когато заданието е неясно или си противоречи' },
|
|
485
|
+
{
|
|
486
|
+
en: 'When it needs something outside the project — access, a password, an install',
|
|
487
|
+
bg: 'Когато му трябва нещо извън проекта — достъп, парола, инсталация',
|
|
488
|
+
},
|
|
489
|
+
{ en: 'When a test fails for a reason outside its own change', bg: 'Когато тест пада по причина извън неговата промяна' },
|
|
490
|
+
{ en: 'When it would have to touch something it is not responsible for', bg: 'Когато трябва да пипне нещо, за което не отговаря' },
|
|
491
|
+
],
|
|
492
|
+
},
|
|
493
|
+
],
|
|
494
|
+
},
|
|
495
|
+
{
|
|
496
|
+
id: 'persona-build-phases',
|
|
497
|
+
stages: ['phase0', 'persona'],
|
|
498
|
+
phase: 'persona',
|
|
499
|
+
when: {
|
|
500
|
+
en: 'The persona, answer 2, second message: phases and result',
|
|
501
|
+
bg: 'Персоната, отговор 2, второ съобщение: фазите и резултатът',
|
|
502
|
+
},
|
|
503
|
+
questions: [
|
|
504
|
+
{
|
|
505
|
+
choose: { en: 'Which stages does it work through?', bg: 'През какви етапи минава?' },
|
|
506
|
+
options: [
|
|
507
|
+
{
|
|
508
|
+
en: 'For work that writes code: Understand (reads the assignment and the code; done when it knows what is missing) → Do (writes the code; done when the code is in place) → Prove (writes a test for each behaviour and runs them all; done when they all pass) → Report (writes the summary; done when it names the files and carries the test output)',
|
|
509
|
+
bg: 'За работа, която пише код: Разбери (чете заданието и кода; свършено, когато знае какво липсва) → Направи (пише кода; свършено, когато кодът е на мястото си) → Докажи (пише тест за всяко поведение и пуска всички; свършено, когато всички минават) → Докладвай (пише резюмето; свършено, когато назовава файловете и съдържа изхода от тестовете)',
|
|
510
|
+
},
|
|
511
|
+
{
|
|
512
|
+
en: 'For bugs: Reproduce (writes a test that fails because of the bug; done when it fails) → Fix (changes the code; done when that test passes) → Prove (runs all the tests; done when they all pass) → Report (the cause and the fix, with the test output)',
|
|
513
|
+
bg: 'За бъгове: Възпроизведи (пише тест, който пада заради бъга; свършено, когато тестът пада) → Поправи (променя кода; свършено, когато тестът минава) → Докажи (пуска всички тестове; свършено, когато всички минават) → Докладвай (причината и поправката, с изхода от тестовете)',
|
|
514
|
+
},
|
|
515
|
+
{
|
|
516
|
+
en: 'For an audit, with no changes: Read (reads the code and the documents; done when everything needed is read) → Check (runs commands that prove or disprove each claim; done when each has a result) → Report (the findings, each with its evidence)',
|
|
517
|
+
bg: 'За одит, без промени: Прочети (чете кода и документите; свършено, когато всичко нужно е прочетено) → Провери (пуска команди, които доказват или опровергават всяко твърдение; свършено, когато всяко има резултат) → Докладвай (находките, всяка с доказателството си)',
|
|
518
|
+
},
|
|
519
|
+
],
|
|
520
|
+
other: { en: 'something else — describe your stages', bg: 'друго — опиши етапите си' },
|
|
521
|
+
hints: [
|
|
522
|
+
{
|
|
523
|
+
en: 'For each stage: what happens in it, and what shows it is done.',
|
|
524
|
+
bg: 'За всеки етап: какво става в него и кое показва, че е свършен.',
|
|
525
|
+
},
|
|
526
|
+
],
|
|
527
|
+
},
|
|
528
|
+
{
|
|
529
|
+
choose: { en: 'What does it hand back at the end?', bg: 'Какво предава накрая?' },
|
|
530
|
+
options: [
|
|
531
|
+
{
|
|
532
|
+
en: 'A summary: what changed, in which files, with the output of the tests',
|
|
533
|
+
bg: 'Резюме: какво е променено, в кои файлове, с изхода от тестовете',
|
|
534
|
+
},
|
|
535
|
+
{ en: 'A report of findings, with no change to the code', bg: 'Доклад с находки, без промени по кода' },
|
|
536
|
+
],
|
|
537
|
+
},
|
|
538
|
+
{
|
|
539
|
+
choose: {
|
|
540
|
+
en: 'What will the result be judged by? Several are fine.',
|
|
541
|
+
bg: 'По какво ще се съди резултатът? Може няколко.',
|
|
542
|
+
},
|
|
543
|
+
options: [
|
|
544
|
+
{ en: 'All tests pass', bg: 'Всички тестове минават' },
|
|
545
|
+
{ en: 'Every acceptance criterion has a test', bg: 'Всеки критерий за приемане има тест' },
|
|
546
|
+
{ en: 'The build and the linter pass', bg: 'Build-ът и линтерът минават' },
|
|
547
|
+
{ en: 'Nothing outside what is allowed has changed', bg: 'Нищо извън позволеното не е променено' },
|
|
548
|
+
],
|
|
549
|
+
},
|
|
550
|
+
],
|
|
551
|
+
},
|
|
552
|
+
{
|
|
553
|
+
id: 'work',
|
|
554
|
+
stages: ['phase0'],
|
|
555
|
+
phase: 'p0',
|
|
556
|
+
when: { en: 'Phase 0, after the persona: this work', bg: 'Фаза 0, след персоната: тази работа' },
|
|
557
|
+
questions: [
|
|
558
|
+
{
|
|
559
|
+
ask: {
|
|
560
|
+
en: 'What is the ticket or the assignment? Paste it whole: number, title, acceptance criteria.',
|
|
561
|
+
bg: 'Кой е ticket-ът или заданието? Постави го цял: номер, заглавие, критерии за приемане.',
|
|
562
|
+
},
|
|
563
|
+
},
|
|
564
|
+
{
|
|
565
|
+
ask: {
|
|
566
|
+
en: 'What is the goal, in one or two sentences: what must be true when the work is over?',
|
|
567
|
+
bg: 'Каква е целта, с едно-две изречения: какво трябва да е вярно, когато работата приключи?',
|
|
568
|
+
},
|
|
569
|
+
},
|
|
570
|
+
{
|
|
571
|
+
choose: { en: 'Which projects does it touch? Several are fine.', bg: 'Кои проекти засяга? Може няколко.' },
|
|
572
|
+
options: 'projects',
|
|
573
|
+
},
|
|
574
|
+
{ ask: { en: 'What has already been decided or tried?', bg: 'Какво вече е решено или пробвано?' } },
|
|
575
|
+
{
|
|
576
|
+
ask: {
|
|
577
|
+
en: 'What must stay as it is while this work goes on — things others rely on?',
|
|
578
|
+
bg: 'Какво трябва да остане непроменено, докато тече тази работа — неща, на които разчитат други?',
|
|
579
|
+
},
|
|
580
|
+
hints: [
|
|
581
|
+
{
|
|
582
|
+
en: 'Example: the public endpoints of the API; the database schema; the existing tests; the files in .github/; somebody else\'s work on the same branch.',
|
|
583
|
+
bg: 'Пример: публичните endpoint-и на API-то; схемата на базата; съществуващите тестове; файловете в .github/; работата на друг човек в същия клон.',
|
|
584
|
+
},
|
|
585
|
+
],
|
|
586
|
+
},
|
|
587
|
+
{ ask: { en: 'What is still open, and who decides it?', bg: 'Какво още е отворено и кой го решава?' } },
|
|
588
|
+
],
|
|
589
|
+
},
|
|
590
|
+
{
|
|
591
|
+
id: 'phase1-work',
|
|
592
|
+
stages: ['phase1'],
|
|
593
|
+
phase: 'p1',
|
|
594
|
+
when: { en: 'Phase 1, the first message: this work', bg: 'Фаза 1, първото съобщение: тази работа' },
|
|
595
|
+
questions: [
|
|
596
|
+
{
|
|
597
|
+
ask: {
|
|
598
|
+
en: 'The assignment: paste it as you have it — a ticket, a work item, a document or one sentence.',
|
|
599
|
+
bg: 'Заданието: постави го така, както го имаш — ticket, работен елемент, документ или едно изречение.',
|
|
600
|
+
},
|
|
601
|
+
},
|
|
602
|
+
{
|
|
603
|
+
ask: {
|
|
604
|
+
en: 'How will you know the work is done? List the acceptance criteria.',
|
|
605
|
+
bg: 'Как ще разбереш, че работата е свършена? Изброй критериите за приемане.',
|
|
606
|
+
},
|
|
607
|
+
},
|
|
608
|
+
{
|
|
609
|
+
choose: { en: 'Which project is the work in? Several are fine.', bg: 'В кой проект е работата? Може няколко.' },
|
|
610
|
+
options: 'projects',
|
|
611
|
+
},
|
|
612
|
+
{
|
|
613
|
+
ask: {
|
|
614
|
+
en: 'Which language and tools, and which command runs the tests?',
|
|
615
|
+
bg: 'Кой език и кои инструменти, и с коя команда се пускат тестовете?',
|
|
616
|
+
},
|
|
617
|
+
},
|
|
618
|
+
{
|
|
619
|
+
ask: {
|
|
620
|
+
en: 'What must stay as it is while this work goes on?',
|
|
621
|
+
bg: 'Какво трябва да остане непроменено, докато тече тази работа?',
|
|
622
|
+
},
|
|
623
|
+
hints: [
|
|
624
|
+
{
|
|
625
|
+
en: 'Example: the public endpoints of the API; the database schema; the existing tests; the files in .github/.',
|
|
626
|
+
bg: 'Пример: публичните endpoint-и на API-то; схемата на базата; съществуващите тестове; файловете в .github/.',
|
|
627
|
+
},
|
|
628
|
+
],
|
|
629
|
+
},
|
|
630
|
+
],
|
|
631
|
+
},
|
|
632
|
+
{
|
|
633
|
+
id: 'phase1-settings',
|
|
634
|
+
stages: ['phase1'],
|
|
635
|
+
phase: 'p1',
|
|
636
|
+
when: {
|
|
637
|
+
en: 'Phase 1, once the work is clear (and after any follow-up questions): the settings',
|
|
638
|
+
bg: 'Фаза 1, щом работата е ясна (и след уточненията, ако е имало): настройките',
|
|
639
|
+
},
|
|
640
|
+
questions: [
|
|
641
|
+
{
|
|
642
|
+
choose: { en: 'Version control (`vcs`, required):', bg: 'Контрол на версиите (`vcs`, задължително):' },
|
|
643
|
+
options: [
|
|
644
|
+
{ en: 'Yes — a branch before each task and a commit after it', bg: 'Да — клон преди всяка задача и комит след нея' },
|
|
645
|
+
{ en: 'No — files change in place, and there is no way back', bg: 'Не — файловете се променят на място и няма връщане назад' },
|
|
646
|
+
],
|
|
647
|
+
},
|
|
648
|
+
{
|
|
649
|
+
choose: { en: 'Branches, if 1.1 (`branchMode`):', bg: 'Клоновете, ако е 1.1 (`branchMode`):' },
|
|
650
|
+
options: [
|
|
651
|
+
{
|
|
652
|
+
en: 'One branch for the whole session — each task builds on the one before (per-session)',
|
|
653
|
+
bg: 'Един клон за цялата сесия — всяка задача стъпва върху предишната (per-session)',
|
|
654
|
+
},
|
|
655
|
+
{
|
|
656
|
+
en: 'A branch per task — each starts from the same point (per-task)',
|
|
657
|
+
bg: 'Отделен клон за всяка задача — всяка тръгва от едно и също място (per-task)',
|
|
658
|
+
},
|
|
659
|
+
],
|
|
660
|
+
},
|
|
661
|
+
{
|
|
662
|
+
choose: { en: 'If a task fails (`onFailure` of the session, required):', bg: 'Ако задача се провали (`onFailure` на сесията, задължително):' },
|
|
663
|
+
options: [
|
|
664
|
+
{ en: 'Stop — the tasks are a chain', bg: 'Спри — задачите са верига' },
|
|
665
|
+
{ en: 'Carry on with the next — the tasks are independent', bg: 'Продължи със следващата — задачите са независими' },
|
|
666
|
+
],
|
|
667
|
+
},
|
|
668
|
+
{
|
|
669
|
+
choose: { en: 'If a whole session fails (`onFailure` of the plan, required; with one session it makes no difference):', bg: 'Ако цяла сесия се провали (`onFailure` на плана, задължително; при една сесия няма значение):' },
|
|
670
|
+
options: [
|
|
671
|
+
{ en: 'Stop — the later sessions do not start', bg: 'Спри — по-късните сесии не тръгват' },
|
|
672
|
+
{ en: 'Carry on with the next session', bg: 'Продължи със следващата сесия' },
|
|
673
|
+
],
|
|
674
|
+
},
|
|
675
|
+
{
|
|
676
|
+
choose: { en: 'Chats (`conversation`, required):', bg: 'Чатове (`conversation`, задължително):' },
|
|
677
|
+
options: [
|
|
678
|
+
{ en: 'A chat of its own for each session', bg: 'Отделен чат за всяка сесия' },
|
|
679
|
+
{ en: 'One shared chat for all sessions', bg: 'Един общ чат за всички сесии' },
|
|
680
|
+
],
|
|
681
|
+
},
|
|
682
|
+
{
|
|
683
|
+
choose: { en: 'Review (`review`):', bg: 'Рецензия (`review`):' },
|
|
684
|
+
options: [
|
|
685
|
+
{ en: "On, with the session's own model", bg: 'Включена, на модела на сесията' },
|
|
686
|
+
{ en: 'On, with another model — say which', bg: 'Включена, на друг модел — напиши кой' },
|
|
687
|
+
{ en: 'Off', bg: 'Изключена' },
|
|
688
|
+
],
|
|
689
|
+
},
|
|
690
|
+
{
|
|
691
|
+
choose: { en: 'Project files for the chat (`mirror`):', bg: 'Файлове на проекта към чата (`mirror`):' },
|
|
692
|
+
options: [
|
|
693
|
+
{ en: 'No', bg: 'Не' },
|
|
694
|
+
{ en: 'Yes — give the root and the folders', bg: 'Да — напиши корена и папките' },
|
|
695
|
+
],
|
|
696
|
+
},
|
|
697
|
+
{
|
|
698
|
+
choose: { en: 'Name of the run (`plan`):', bg: 'Име на пускането (`plan`):' },
|
|
699
|
+
options: [{ en: '{the name you propose from the goal}', bg: '{името, което предлагаш от целта}' }],
|
|
700
|
+
},
|
|
701
|
+
],
|
|
702
|
+
},
|
|
703
|
+
{
|
|
704
|
+
id: 'phase1-breakdown',
|
|
705
|
+
stages: ['phase1'],
|
|
706
|
+
phase: 'p1',
|
|
707
|
+
when: {
|
|
708
|
+
en: 'Phase 1, the last message: the breakdown, in prose, and nothing written yet',
|
|
709
|
+
bg: 'Фаза 1, последното съобщение: разбивката с думи, още без JSON',
|
|
710
|
+
},
|
|
711
|
+
lead: [
|
|
712
|
+
{ en: 'Sessions: {count}. Tasks: {count}.', bg: 'Сесии: {брой}. Задачи: {брой}.' },
|
|
713
|
+
{ en: 'Session `{name}`: {goal}', bg: 'Сесия `{име}`: {цел}' },
|
|
714
|
+
{ en: '- Task `{title}`: {what it does}. Checks: {which}.', bg: '- Задача `{заглавие}`: {какво прави}. Проверки: {какви}.' },
|
|
715
|
+
{
|
|
716
|
+
en: 'Criterion → check: {each criterion of the assignment → the check on the output that names it — for a test, "✔ " and the test named after the criterion}.',
|
|
717
|
+
bg: 'Критерий → проверка: {всеки критерий от заданието → проверката по изхода, която го назовава — за тест, „✔ “ и тестът, кръстен на критерия}.',
|
|
718
|
+
},
|
|
719
|
+
{
|
|
720
|
+
en: 'Settings: version control {…}; if a task fails {…}; if a session fails {…}; chats {…}; review {…}; files for the chat {…}; run name {…}.',
|
|
721
|
+
bg: 'Настройки: контрол на версиите {…}; при провал на задача {…}; при провал на сесия {…}; чатове {…}; рецензия {…}; файлове към чата {…}; име на пускането {…}.',
|
|
722
|
+
},
|
|
723
|
+
{ en: 'Decided by me without asking you: {the fields, or "nothing"}.', bg: 'Решено от мен, без да съм те питала: {полетата или „нищо“}.' },
|
|
724
|
+
],
|
|
725
|
+
questions: [
|
|
726
|
+
{
|
|
727
|
+
choose: { en: 'Is this right?', bg: 'Така ли е?' },
|
|
728
|
+
options: [
|
|
729
|
+
{ en: 'Right as it is: write the JSON.', bg: 'Така е добре: напиши JSON-а.' },
|
|
730
|
+
{ en: 'I want a change — I will say what.', bg: 'Искам промяна — ще напиша каква.' },
|
|
731
|
+
],
|
|
732
|
+
other: false,
|
|
733
|
+
},
|
|
734
|
+
],
|
|
735
|
+
},
|
|
736
|
+
...['p3', 'p4'].map((phase) => ({
|
|
737
|
+
id: phase === 'p3' ? 'record-3' : 'record-4',
|
|
738
|
+
stages: [phase === 'p3' ? 'phase3' : 'phase4'],
|
|
739
|
+
phase,
|
|
740
|
+
when: phase === 'p3'
|
|
741
|
+
? {
|
|
742
|
+
en: 'Phase 3, once the operator has said a task did not end done: asking for the record of the tasks you need, named in {tasks}',
|
|
743
|
+
bg: 'Фаза 3, щом операторът е казал, че задача не е завършила готова: искане на записа на задачите, които ти трябват, назовани в {задачите}',
|
|
744
|
+
}
|
|
745
|
+
: {
|
|
746
|
+
en: 'Phase 4, once the operator has said the run finished: asking for the record of the tasks you still need, named in {tasks}',
|
|
747
|
+
bg: 'Фаза 4, щом операторът е казал, че пускането е приключило: искане на записа на задачите, които още ти трябват, назовани в {задачите}',
|
|
748
|
+
},
|
|
749
|
+
lead: [
|
|
750
|
+
{ en: 'I need the record of: {tasks}.', bg: 'Трябва ми записът на: {задачите}.' },
|
|
751
|
+
{ en: '1. On `/history`, press **"Choose tasks"**.', bg: '1. В `/history` натисни **„Избери задачи“**.' },
|
|
752
|
+
{ en: '2. Tick {tasks}.', bg: '2. Отметни {задачите}.' },
|
|
753
|
+
{
|
|
754
|
+
en: '3. Press **"Download plan, work and runner for the {n} chosen, as one file"**.',
|
|
755
|
+
bg: '3. Натисни **„Изтегли план, работа и runner за избраните {n}, в един файл“**.',
|
|
756
|
+
},
|
|
757
|
+
{ en: '4. Paste the contents of the file here.', bg: '4. Постави съдържанието на файла тук.' },
|
|
758
|
+
],
|
|
759
|
+
questions: [],
|
|
760
|
+
})),
|
|
761
|
+
{
|
|
762
|
+
id: 'phase4-proven',
|
|
763
|
+
stages: ['phase4'],
|
|
764
|
+
phase: 'p4',
|
|
765
|
+
when: {
|
|
766
|
+
en: 'Phase 4, after the table: every criterion proven',
|
|
767
|
+
bg: 'Фаза 4, след таблицата: всеки критерий е доказан',
|
|
768
|
+
},
|
|
769
|
+
lead: [{ en: 'The assignment is carried out: every criterion is proven.', bg: 'Заданието е изпълнено: всеки критерий е доказан.' }],
|
|
770
|
+
questions: [{ ask: { en: 'What is the next piece of work?', bg: 'Коя е следващата работа?' } }],
|
|
771
|
+
},
|
|
772
|
+
{
|
|
773
|
+
id: 'phase4-unproven',
|
|
774
|
+
stages: ['phase4'],
|
|
775
|
+
phase: 'p4',
|
|
776
|
+
when: {
|
|
777
|
+
en: 'Phase 4, after the table: something claimed only or missing',
|
|
778
|
+
bg: 'Фаза 4, след таблицата: нещо е само твърдение или липсва',
|
|
779
|
+
},
|
|
780
|
+
lead: [{ en: 'Not proven: {the criteria}.', bg: 'Не е доказано: {критериите}.' }],
|
|
781
|
+
questions: [
|
|
782
|
+
{
|
|
783
|
+
choose: { en: 'What do we do?', bg: 'Какво правим?' },
|
|
784
|
+
options: [
|
|
785
|
+
{
|
|
786
|
+
en: 'A read-only task that proves what is only claimed, by running it — for "claimed only"',
|
|
787
|
+
bg: 'Задача само за четене, която доказва твърдяното, като го пуска — за „само твърдение“',
|
|
788
|
+
},
|
|
789
|
+
{
|
|
790
|
+
en: 'Change a task and run it again — the work is right for the task, the task was asked wrongly',
|
|
791
|
+
bg: 'Промени задача и я пусни отново — работата е вярна за задачата, задачата е поискана грешно',
|
|
792
|
+
},
|
|
793
|
+
{
|
|
794
|
+
en: 'Put the repository back and solve it differently — the approach is wrong',
|
|
795
|
+
bg: 'Върни хранилището и реши иначе — грешен е подходът',
|
|
796
|
+
},
|
|
797
|
+
{
|
|
798
|
+
en: 'A new session of tasks — what is missing was never asked for',
|
|
799
|
+
bg: 'Нова сесия със задачи — липсващото никога не е било поискано',
|
|
800
|
+
},
|
|
801
|
+
],
|
|
802
|
+
},
|
|
803
|
+
],
|
|
804
|
+
},
|
|
805
|
+
];
|
|
806
|
+
export const OPENING = {
|
|
807
|
+
phase0: {
|
|
808
|
+
greeting: {
|
|
809
|
+
en: "Hello, I'm Kerrigan, Queen of Blades! I'll help you with writing down how work is done here, how the tasks should be carried out and what this work is.",
|
|
810
|
+
bg: 'Здравей, аз съм Kerrigan, Queen of Blades! Ще ти помагам с описването на това как се работи тук, как да се изпълняват задачите и каква е тази работа.',
|
|
811
|
+
},
|
|
812
|
+
firstMessage: 'org-work',
|
|
813
|
+
},
|
|
814
|
+
persona: {
|
|
815
|
+
greeting: {
|
|
816
|
+
en: "Hello, I'm Kerrigan, Queen of Blades! I'll help you with settling how the tasks will be carried out.",
|
|
817
|
+
bg: 'Здравей, аз съм Kerrigan, Queen of Blades! Ще ти помагам с уточняването на това как ще се изпълняват задачите.',
|
|
818
|
+
},
|
|
819
|
+
firstMessage: 'persona-ask',
|
|
820
|
+
},
|
|
821
|
+
phase1: {
|
|
822
|
+
greeting: {
|
|
823
|
+
en: "Hello, I'm Kerrigan, Queen of Blades! I'll help you with planning this piece of work, getting it running and checking the result.",
|
|
824
|
+
bg: 'Здравей, аз съм Kerrigan, Queen of Blades! Ще ти помагам с планирането на тази работа, пускането ѝ и проверката на резултата.',
|
|
825
|
+
},
|
|
826
|
+
firstMessage: 'phase1-work',
|
|
827
|
+
},
|
|
828
|
+
};
|
|
829
|
+
function projectOptions(projects, lang) {
|
|
830
|
+
return projects.map((p) => {
|
|
831
|
+
const label = p.name || (lang === 'bg' ? 'проектът по подразбиране' : 'the default project');
|
|
832
|
+
return `${label} — \`${p.rootDir}\``;
|
|
833
|
+
});
|
|
834
|
+
}
|
|
835
|
+
function isChoose(q) {
|
|
836
|
+
return 'choose' in q;
|
|
837
|
+
}
|
|
838
|
+
/**
|
|
839
|
+
* The last line of a message, which is also its "what happens next". Fixed per shape so the
|
|
840
|
+
* operator reads the same instruction for the same kind of message.
|
|
841
|
+
*/
|
|
842
|
+
function answerLine(questions, lang) {
|
|
843
|
+
const choices = questions.filter(isChoose).length;
|
|
844
|
+
const asks = questions.length - choices;
|
|
845
|
+
// No questions, or one plain question: the last line already says what happens next.
|
|
846
|
+
if (questions.length === 0 || (questions.length === 1 && choices === 0))
|
|
847
|
+
return '';
|
|
848
|
+
if (questions.length === 1 && choices === 1)
|
|
849
|
+
return lang === 'bg' ? 'Отговори с номера.' : 'Answer with the number.';
|
|
850
|
+
if (choices === 0) {
|
|
851
|
+
return lang === 'bg'
|
|
852
|
+
? 'Отговори под номера на всеки въпрос; където нямате такова, напиши „няма“.'
|
|
853
|
+
: 'Answer under the number of each question; where you have none, write "none".';
|
|
854
|
+
}
|
|
855
|
+
const first = questions.findIndex(isChoose) + 1;
|
|
856
|
+
if (asks === 0) {
|
|
857
|
+
return lang === 'bg'
|
|
858
|
+
? `Отговори с номерата на избраните опции, например \`${first}.1 ${first + 1}.2\`.`
|
|
859
|
+
: `Answer with the numbers of the options you pick, for example \`${first}.1 ${first + 1}.2\`.`;
|
|
860
|
+
}
|
|
861
|
+
return lang === 'bg'
|
|
862
|
+
? `Отговори под номера на всеки въпрос: с думи, а където има опции — с номера им, например \`${first}.1\`.`
|
|
863
|
+
: `Answer under the number of each question: in words, and where there are options, with their number, for example \`${first}.1\`.`;
|
|
864
|
+
}
|
|
865
|
+
/**
|
|
866
|
+
* The phase line a message opens with. The persona messages are shared by two states: inside the
|
|
867
|
+
* full first-run interview they are phase 0 like the rest of it, and on their own — the organisation
|
|
868
|
+
* written, the persona missing — they are the step before phase 1.
|
|
869
|
+
*/
|
|
870
|
+
export function phaseLineOf(m, stages, lang) {
|
|
871
|
+
const key = m.phase === 'persona' ? (stages.includes('phase0') ? 'p0' : 'beforeP1') : m.phase;
|
|
872
|
+
return PHASE_LINES[key][lang];
|
|
873
|
+
}
|
|
874
|
+
/** One message as the operator is to see it, as a list of lines without the quotation marks. */
|
|
875
|
+
export function renderMessage(m, projects, lang, stages = m.stages) {
|
|
876
|
+
const lines = [phaseLineOf(m, stages, lang)];
|
|
877
|
+
// Two plain lines in a row are one paragraph once a chat renders them, so a breakdown's "Sessions"
|
|
878
|
+
// and "Session" lines would run together, and a plain line straight after a list item is read as
|
|
879
|
+
// part of that item. A blank line keeps them apart; only items of one list stay together.
|
|
880
|
+
const isItem = (l) => /^(- |\d+\. )/.test(l);
|
|
881
|
+
for (const l of m.lead ?? []) {
|
|
882
|
+
const prev = lines[lines.length - 1];
|
|
883
|
+
if (prev !== undefined && !(isItem(prev) && isItem(l[lang])))
|
|
884
|
+
lines.push('');
|
|
885
|
+
lines.push(l[lang]);
|
|
886
|
+
}
|
|
887
|
+
if (m.questions.length)
|
|
888
|
+
lines.push('');
|
|
889
|
+
// Hints sit under the question they belong to, indented into its list item and in italics, so the
|
|
890
|
+
// operator sees at a glance which lines they can skip. Each is its own paragraph, a blank line
|
|
891
|
+
// before it: an indented line straight under a list item is, to Markdown, the same paragraph, and
|
|
892
|
+
// the first live run showed every "Example:" glued onto the end of its question.
|
|
893
|
+
const hintLines = (q) => (q.hints ?? []).flatMap((h) => ['', ` *${h[lang]}*`]);
|
|
894
|
+
// The options after hints need the same blank line, or they read as part of the last hint.
|
|
895
|
+
const beforeOptions = (q) => (q.hints?.length ? [''] : []);
|
|
896
|
+
const single = m.questions.length === 1 && isChoose(m.questions[0]);
|
|
897
|
+
m.questions.forEach((q, i) => {
|
|
898
|
+
const n = i + 1;
|
|
899
|
+
if (!isChoose(q)) {
|
|
900
|
+
lines.push(`${n}. ${q.ask[lang]}`, ...hintLines(q));
|
|
901
|
+
return;
|
|
902
|
+
}
|
|
903
|
+
const listed = q.options === 'projects' ? projectOptions(projects, lang) : q.options.map((o) => o[lang]);
|
|
904
|
+
const last = q.options === 'projects' ? OTHER_FOLDER[lang] : q.other === false ? undefined : (q.other ?? OTHER)[lang];
|
|
905
|
+
const options = last ? [...listed, last] : listed;
|
|
906
|
+
if (single) {
|
|
907
|
+
lines.push(q.choose[lang], ...hintLines(q), ...beforeOptions(q));
|
|
908
|
+
options.forEach((o, j) => lines.push(`${j + 1}. ${o}`));
|
|
909
|
+
}
|
|
910
|
+
else {
|
|
911
|
+
lines.push(`${n}. ${q.choose[lang]}`, ...hintLines(q), ...beforeOptions(q));
|
|
912
|
+
options.forEach((o, j) => lines.push(` - ${n}.${j + 1} ${o}`));
|
|
913
|
+
}
|
|
914
|
+
});
|
|
915
|
+
const answer = answerLine(m.questions, lang);
|
|
916
|
+
if (answer)
|
|
917
|
+
lines.push('', answer);
|
|
918
|
+
return lines;
|
|
919
|
+
}
|
|
920
|
+
/**
|
|
921
|
+
* The script section of the brief, for the stages this state of the brief can reach.
|
|
922
|
+
*
|
|
923
|
+
* Each message is printed under a heading that is for the model — when to send it — and as a
|
|
924
|
+
* quotation that is for the operator, phase line included. The heading carries no number of its
|
|
925
|
+
* own, so nothing in it can be mistaken for the numbering the operator answers with.
|
|
926
|
+
*/
|
|
927
|
+
export function scriptSection(stages, projects, lang) {
|
|
928
|
+
const wanted = SCRIPT.filter((m) => m.stages.some((s) => stages.includes(s)));
|
|
929
|
+
const blocks = wanted.map((m) => {
|
|
930
|
+
const quoted = renderMessage(m, projects, lang, stages).map((l) => (l ? `> ${l}` : '>'));
|
|
931
|
+
return `### ${m.when[lang]}\n\n${quoted.join('\n')}`;
|
|
932
|
+
});
|
|
933
|
+
const head = lang === 'bg'
|
|
934
|
+
? `## Въпросите, дословно
|
|
935
|
+
|
|
936
|
+
Всяко съобщение, в което питаш оператора нещо, е тук — дословно, в реда, в който идват. **Копирай го
|
|
937
|
+
точно:** същите въпроси, в същия ред, със същите номера, същите опции и същите редове *Пример:*. Не
|
|
938
|
+
добавяй въпрос, не махай, не сливай, не разделяй, не преформулирай и не пренареждай — операторът учи
|
|
939
|
+
разговора, а това става само ако той е един и същ всеки път. Заглавието над цитата е за теб: казва
|
|
940
|
+
кога се праща съобщението; операторът вижда само цитираното, без знака \`>\`.
|
|
941
|
+
|
|
942
|
+
- **Първият ред на всеки цитат е редът за фазата.** Копираш го както е; не го сменяш и не добавяш
|
|
943
|
+
друг.
|
|
944
|
+
- **Номерата са само цифри.** Въпросите са 1, 2, 3; опциите под въпрос 2 са 2.1, 2.2, 2.3. Никога
|
|
945
|
+
букви. Съобщение с един-единствен избор номерира опциите си 1, 2, 3.
|
|
946
|
+
- **Попълваш само това в {скоби}** — път, име, брой, присъда — и нищо друго не пишеш наново.
|
|
947
|
+
**Съобщение с непопълнени {скоби} не се изпраща никога**: ако не знаеш с какво да ги попълниш,
|
|
948
|
+
значи съобщението не е за сега.
|
|
949
|
+
- **Препоръка:** на въпрос с опции, освен на тези за това какво операторът има или знае, може да
|
|
950
|
+
добавиш след една опция *(препоръчвам — причината в няколко думи)*. Само ако имаш причина.
|
|
951
|
+
- **Вече казано:** ако отговорът на въпрос вече е даден — в документите на оператора по-горе или
|
|
952
|
+
по-рано в този разговор — въпросът остава на мястото си, а под него, след празен ред и със същия
|
|
953
|
+
отстъп като редовете *Пример:*, пишеш \`${ALREADY_SAID.bg} …\` с отговора — отделен ред, не в края на
|
|
954
|
+
въпроса; на избор отбелязваш опцията с *(вече казано)*. Отговорът е целият, не етикет: за
|
|
955
|
+
заданието — заглавието, целта и контекстът от „Тази работа“, не само заглавието; за критериите —
|
|
956
|
+
всеки от тях. Операторът потвърждава това, което вижда, и не може да потвърди нещо, което не е
|
|
957
|
+
показано. Последният ред
|
|
958
|
+
на цитата тогава е точно един от тези два: когато всеки въпрос е вече казан — *${ON_RECORD_ALL.bg}*
|
|
959
|
+
— а когато само някои — *${ON_RECORD_MIXED.bg}*
|
|
960
|
+
- **Около цитата:** преди него — само поздравът, и то само в първото съобщение; след него — нищо: без
|
|
961
|
+
„Очаквам отговорите ти“ и без „Когато си готов…“. Последният ред на цитата вече казва какво следва.
|
|
962
|
+
Съобщенията, които не питат нищо, също започват с реда за фазата си и свършват на последната си
|
|
963
|
+
стъпка. Редът за фаза 2 е \`${PHASE_LINES.p2.bg}\`.
|
|
964
|
+
- **Единственото място за твои въпроси** е мъгляв или липсващ отговор във фаза 1: тогава, преди
|
|
965
|
+
настройките, пращаш едно съобщение с уточнения — редът за фазата, само номерирани въпроси, 1, 2, 3,
|
|
966
|
+
с опции 1.1, 1.2, когато отговорите могат да се изброят, и същия последен ред като тук.
|
|
967
|
+
|
|
968
|
+
Съобщенията, които не питат нищо — JSON-ът, стъпките в приложението, диагнозата, таблицата с
|
|
969
|
+
доказателствата — следват описанието във фазата си.`
|
|
970
|
+
: `## The questions, word for word
|
|
971
|
+
|
|
972
|
+
Every message in which you ask the operator something is here — word for word, in the order they
|
|
973
|
+
come. **Copy it exactly:** the same questions, in the same order, with the same numbers, the same
|
|
974
|
+
options and the same *Example:* lines. Do not add a question, drop one, merge, split, reword or
|
|
975
|
+
reorder — the operator learns the conversation, and that only works if it is the same every time. The
|
|
976
|
+
heading above each quotation is for you: it says when the message is sent; the operator sees only
|
|
977
|
+
what is quoted, without the \`>\`.
|
|
978
|
+
|
|
979
|
+
- **The first line of every quotation is the phase line.** Copy it as it is; do not change it and do
|
|
980
|
+
not add another.
|
|
981
|
+
- **Numbers are digits only.** Questions are 1, 2, 3; the options under question 2 are 2.1, 2.2, 2.3.
|
|
982
|
+
Never letters. A message with one single choice numbers its options 1, 2, 3.
|
|
983
|
+
- **You fill in only what is in {braces}** — a path, a name, a count, a verdict — and write nothing
|
|
984
|
+
else afresh. **A message with unfilled {braces} is never sent**: if you do not know what goes in
|
|
985
|
+
them, the message is not for now.
|
|
986
|
+
- **Recommending:** on a question with options, except those about what the operator has or knows,
|
|
987
|
+
you may add after one option *(recommended — the reason in a few words)*. Only when you have one.
|
|
988
|
+
- **Already said:** if a question has already been answered — in the operator's documents above or
|
|
989
|
+
earlier in this conversation — the question stays where it is and, under it, after a blank line
|
|
990
|
+
and indented like the *Example:* lines, you write \`${ALREADY_SAID.en} …\` with the answer — a line
|
|
991
|
+
of its own, not the end of the question; on a choice you mark the option *(already said)*. The
|
|
992
|
+
answer is the whole of it, not a label: for the assignment, the title, the goal and the context from
|
|
993
|
+
"This work", not the title alone; for the criteria, every one of them. The operator confirms what
|
|
994
|
+
they see, and cannot confirm what is not shown.
|
|
995
|
+
The last line of the quotation is then exactly one of these two: when every question is already
|
|
996
|
+
answered — *${ON_RECORD_ALL.en}* — and when only some are — *${ON_RECORD_MIXED.en}*
|
|
997
|
+
- **Around the quotation:** before it, only the greeting, and only in the first message; after it,
|
|
998
|
+
nothing: no "I look forward to your answers", no "When you are ready…". The quotation's last line
|
|
999
|
+
already says what happens next. Messages that ask nothing also open with their phase line and end
|
|
1000
|
+
on their last step. The phase 2 line is \`${PHASE_LINES.p2.en}\`.
|
|
1001
|
+
- **The one place for questions of your own** is a vague or missing answer in phase 1: then, before
|
|
1002
|
+
the settings, you send one message of follow-ups — the phase line, numbered questions only, 1, 2,
|
|
1003
|
+
3, with options 1.1, 1.2 where the answers can be listed, and the same last line as here.
|
|
1004
|
+
|
|
1005
|
+
Messages that ask nothing — the JSON, the steps in the app, the diagnosis, the table of evidence —
|
|
1006
|
+
follow the description in their phase.`;
|
|
1007
|
+
return `
|
|
1008
|
+
${head}
|
|
1009
|
+
|
|
1010
|
+
${blocks.join('\n\n')}
|
|
1011
|
+
`;
|
|
1012
|
+
}
|