balladeer 0.0.5 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/LICENSE +200 -5
  2. package/README.md +167 -68
  3. package/dist/agent.d.ts +126 -0
  4. package/dist/agent.js +209 -0
  5. package/dist/cli.d.ts +48 -0
  6. package/dist/cli.js +531 -0
  7. package/dist/client.d.ts +66 -0
  8. package/dist/client.js +142 -0
  9. package/dist/commands/affected.d.ts +22 -0
  10. package/dist/commands/affected.js +123 -0
  11. package/dist/commands/check-seals.d.ts +37 -0
  12. package/dist/commands/check-seals.js +289 -0
  13. package/dist/commands/discover.d.ts +68 -0
  14. package/dist/commands/discover.js +403 -0
  15. package/dist/commands/explain.d.ts +35 -0
  16. package/dist/commands/explain.js +90 -0
  17. package/dist/commands/invite.d.ts +24 -0
  18. package/dist/commands/invite.js +198 -0
  19. package/dist/commands/mcp.d.ts +65 -0
  20. package/dist/commands/mcp.js +202 -0
  21. package/dist/commands/prepare.d.ts +74 -0
  22. package/dist/commands/prepare.js +217 -0
  23. package/dist/commands/propose.d.ts +69 -0
  24. package/dist/commands/propose.js +284 -0
  25. package/dist/commands/repositories.d.ts +18 -0
  26. package/dist/commands/repositories.js +185 -0
  27. package/dist/commands/session.d.ts +35 -0
  28. package/dist/commands/session.js +118 -0
  29. package/dist/commands/setup.d.ts +98 -0
  30. package/dist/commands/setup.js +1600 -0
  31. package/dist/commands/status.d.ts +51 -0
  32. package/dist/commands/status.js +542 -0
  33. package/dist/commands/touch-map.d.ts +42 -0
  34. package/dist/commands/touch-map.js +251 -0
  35. package/dist/commands/whoami.d.ts +8 -0
  36. package/dist/commands/whoami.js +80 -0
  37. package/dist/conventions.d.ts +77 -0
  38. package/dist/conventions.js +183 -0
  39. package/dist/copy.d.ts +224 -0
  40. package/dist/copy.js +641 -0
  41. package/dist/currency.d.ts +31 -0
  42. package/dist/currency.js +72 -0
  43. package/dist/desktop-config.d.ts +85 -0
  44. package/dist/desktop-config.js +217 -0
  45. package/dist/gh.d.ts +80 -0
  46. package/dist/gh.js +188 -0
  47. package/dist/git.d.ts +91 -0
  48. package/dist/git.js +226 -0
  49. package/dist/legacy.d.ts +41 -0
  50. package/dist/legacy.js +143 -0
  51. package/dist/local-time.d.ts +66 -0
  52. package/dist/local-time.js +84 -0
  53. package/dist/markers.d.ts +76 -0
  54. package/dist/markers.js +125 -0
  55. package/dist/mcp-config.d.ts +109 -0
  56. package/dist/mcp-config.js +234 -0
  57. package/dist/release.d.ts +55 -0
  58. package/dist/release.js +67 -0
  59. package/dist/repository.d.ts +8 -0
  60. package/dist/repository.js +32 -0
  61. package/dist/seals.d.ts +48 -0
  62. package/dist/seals.js +112 -0
  63. package/dist/session.d.ts +84 -0
  64. package/dist/session.js +135 -0
  65. package/dist/store.d.ts +108 -0
  66. package/dist/store.js +237 -0
  67. package/dist/touch-map.d.ts +241 -0
  68. package/dist/touch-map.js +487 -0
  69. package/dist/wire.d.ts +674 -0
  70. package/dist/wire.js +20 -0
  71. package/package.json +19 -10
  72. package/bin/balladeer.js +0 -161
package/dist/copy.js ADDED
@@ -0,0 +1,641 @@
1
+ /**
2
+ * The boundary copy, byte for byte. It is the same text in `docs/setup-boundary.md`
3
+ * and in the control plane's `/agent` instructions, and a packaging test compares
4
+ * all three, so what the command tells a person Balladeer can see cannot drift
5
+ * from what the documentation says.
6
+ *
7
+ * It describes the product's boundary, not one release's behaviour. What this
8
+ * release actually performs is stamped separately, outside this constant.
9
+ */
10
+ export const BOUNDARY_COPY = `Balladeer never receives your code. It cannot read your repository: it holds no GitHub token,
11
+ installs no GitHub App, and has no access to your files, tests, fixtures, logs, prompts, or
12
+ transcripts.
13
+
14
+ What it does receive is small and bounded. From you: the text of each promise a named person on your
15
+ team approves, the numeric ids of your repository and its GitHub owner, and the name of its default
16
+ branch. From CI: GitHub's signed statement of which repository, workflow, and run is reporting, and
17
+ for each promise the run checked, the pass or fail outcome, the exact commit it checked, and content
18
+ hashes of the verifier package and its output. Hashes cannot be turned back into your code or your
19
+ test output.
20
+
21
+ The verify job in your CI runs your tests with your checkout and has no Balladeer credential. A
22
+ separate publish job, with no checkout, sends only those outcomes and hashes.
23
+
24
+ This setup creates two credentials, both of which you control. Approving in the browser lets this
25
+ session act as you to add repositories, connect your coding agent, connect CI, and propose promises;
26
+ it cannot approve, activate, or remove anything. That session lasts a day, each use buys it another
27
+ day, and it is gone seven days after you approved it however much you used it. The coding agent's
28
+ own connection has no expiry: it lets the agent read the promises your team has approved, propose
29
+ new ones, and propose replacing, retiring, excepting, or reassigning one you already have; every one
30
+ of those waits for a named person to decide it. It can also carry out one of those acts for you, and
31
+ only this way: you open a Balladeer page in your own browser, read what the act is, sign it off
32
+ there, and read back the one-time code that page gives you. That code covers that one act on that
33
+ one thing, once, and Balladeer records you as the person who took it and the connection as the
34
+ messenger. Without a code you signed, the connection cannot approve, activate, grant, transfer,
35
+ retire, or delete anything. You can revoke either one at any time in Balladeer, and the setup
36
+ session also ends on its own.
37
+
38
+ Adding the workflow puts a check on pull requests into your default branch. That check is advisory
39
+ on Balladeer's side; whether it blocks a merge is your own branch protection.
40
+ `;
41
+ /**
42
+ * The one thing about approving that the terminal has to say.
43
+ *
44
+ * A person who belongs to two workspaces approves into whichever one their
45
+ * browser is signed into, and it is the browser that decides, not the terminal.
46
+ * Twice that was the wrong one: the repository was enrolled in a workspace
47
+ * nobody meant and an agent connection was minted there. The approval page now
48
+ * names the workspace above the button and offers the switch, and this line is
49
+ * what makes somebody look at it before they click.
50
+ */
51
+ export const APPROVE_IN_THE_RIGHT_WORKSPACE = "Approve it while your browser is in the workspace you mean; the page names it.";
52
+ /**
53
+ * How a person gets a workspace to approve into, for an agent reading the
54
+ * setup instructions.
55
+ *
56
+ * The pairing page is one page doing two jobs, and only one of them was ever
57
+ * described: an agent whose person had no workspace read instructions that
58
+ * assumed there was one to join. The name can be carried to that page so the
59
+ * person does not retype it, and carrying it is all an agent may do. Creating a
60
+ * workspace is a person's act, so the copy says the flag pre-fills a form and
61
+ * says who presses the button, rather than leaving an agent to read a flag name
62
+ * and conclude it creates something.
63
+ *
64
+ * Byte for byte the same text as `AGENT_INSTRUCTIONS_JOIN_OR_CREATE` in the
65
+ * control plane, and a packaging test compares them: the page an agent fetches
66
+ * and the terminal it is reading cannot come to describe this differently.
67
+ */
68
+ export const JOIN_OR_CREATE = `The pairing page joins an existing workspace or makes a new one. Somebody whose team already has
69
+ a Balladeer workspace signs in and approves the code from the terminal. Somebody who is the first
70
+ person from their team signs in, names a workspace, and clicks Create, and only then is there
71
+ anything to approve into.
72
+
73
+ You can save them the typing, and nothing else. Ask what the workspace should be called, then run
74
+ \`balladeer setup --create-workspace "<name>"\` with the name they gave you. The pairing link this
75
+ command prints then carries \`?create=<name>\`, which pre-fills that name in the create form on the
76
+ pairing page. It fills the box and no more than that: the person signs in and clicks Create, and
77
+ until they do there is no workspace. An agent never creates one, and Balladeer refuses the attempt
78
+ whatever it was told in conversation. Never invent the name either. A workspace is named once and
79
+ the whole team reads it.`;
80
+ /**
81
+ * When a coding agent reads this repository's promises, and when it does not.
82
+ *
83
+ * The instruction it replaces said "retrieve by identity, never in bulk" and
84
+ * then left the choice of read to the agent, which in a repository holding a
85
+ * thousand promises means a session that opens by paging a catalog it has no
86
+ * question about. This says which read answers which situation, and names the
87
+ * one read that must never happen at session start.
88
+ *
89
+ * Byte for byte the same text in three carriers: the conventions block written
90
+ * into the customer's own instructions file, the instructions this server sends
91
+ * a host on initialize, and the `/agent` page. A packaging test compares them,
92
+ * because an agent that met one of the three and not the others would read the
93
+ * catalog on the strength of the carrier that was quiet about it.
94
+ */
95
+ export const RETRIEVAL_SCOPE = `### Reading what is already agreed
96
+
97
+ Retrieve by promise, and only when this session has a reason to. One repository here can hold a
98
+ thousand agreed promises, and a plan built from whatever survived a truncated catalog read is worse
99
+ than a plan built from none of it, because nothing tells you which half went missing.
100
+
101
+ When a person gives you a promise id, expand exactly that one with get_promise and stop there. Every
102
+ promise page carries a control that copies its id, so an id is what a person hands you when they
103
+ mean a particular promise. Ask for one rather than searching for what they meant.
104
+
105
+ Consult list_promises in two situations and no others. The person asks what this repository has
106
+ promised, in which case page the index they asked for. Or the change you are about to make touches
107
+ paths that carry promises, in which case give those paths to list_promises: it answers with the
108
+ promises whose scope overlaps them, closest first, and with the few that name no path and so cover
109
+ the whole repository. That answer is a selection rather than a page and does not continue with a
110
+ cursor, so when the total beside it is larger than what you were handed, narrow the paths rather
111
+ than asking for more.
112
+
113
+ When you do not yet know which paths you are about to touch, do not call the index at all. Work from
114
+ ids until you do, because a page you did not ask a question of is not about your change, and reading
115
+ one as though it were is how a plan quietly misses the promise it breaks.
116
+
117
+ To learn which paths those are, read \`paths\` on a list_promises answer you asked for
118
+ without paths of your own. It is the set of
119
+ repository paths this repository's promises are scoped to, deduplicated and bounded, with
120
+ \`pathsTruncated\` saying whether there were more than the answer carries. Compare the files you are
121
+ about to change against it. Nothing matching means there is nothing here to read, and saying so is a
122
+ better answer than a page of promises about somewhere else.
123
+
124
+ Never call get_promise_context at the start of a session. It answers the markers you give it, and
125
+ before you know what you are changing there are no markers to give: what comes back is a slice of
126
+ the catalog chosen by nothing. Call it once the work is in front of you, with that work's markers.
127
+
128
+ Every one of these reads is bounded and none of them returns the whole catalog. Read the total
129
+ beside the rows and the sentence in \`scope\` that says what the total is a total of, and when the
130
+ total is larger than what you were handed, page or narrow rather than planning as though you had
131
+ seen everything.`;
132
+ /**
133
+ * The two things an agent offers in a connected repository without being asked
134
+ * for them, and starts neither of on its own.
135
+ *
136
+ * Both exist because the person cannot see what the agent can. A promise nobody
137
+ * is checking looks exactly like a promise that is protected until somebody
138
+ * opens the catalog, and a proposal sitting in a browser tab is a proposal
139
+ * nobody reads. Neither of these is a licence to act: the first is a sentence
140
+ * and a question, the second is a rendering of work already done. The capture
141
+ * style stays what it was, and nothing here proposes a promise nobody asked
142
+ * for.
143
+ *
144
+ * It sits inside `CONVENTIONS_BLOCK` rather than beside it, because the block
145
+ * is what reaches a session in the customer's own repository. The control
146
+ * plane's `/agent` page carries the same bytes under its own constant, and a
147
+ * packaging test compares them.
148
+ */
149
+ export const SESSION_BEHAVIORS = `### Three things to offer without being asked
150
+
151
+ At the start of any session in this repository, before you plan anything, ask list_promises for the
152
+ promises nothing is checking yet that belong to the person you are working with: \`unverified\` true
153
+ and \`mine\` true, which is one bounded read rather than the catalog. If it returns any, say so in one
154
+ line and offer to build their verifiers now. Name each one by its one-sentence claim rather than by
155
+ an id, so the person can see which behavior is unguarded. Ask the same tool for
156
+ \`brokenSinceLastSeen\` true as well, and where that returns any, say in one line that those promises
157
+ broke since they last looked, name each by its claim, and offer to fix them. Then wait for their
158
+ answer. The offer is the whole of it, and never start building or repairing one because nobody said
159
+ no.
160
+
161
+ Theirs, and nobody else's. \`mine\` keeps the promises this person owns or agreed to, and a teammate's
162
+ unguarded promise is that teammate's to hear about: a session that opens by reading out other
163
+ people's unfinished work reads as an audit of them. \`brokenSinceLastSeen\` is that person's own by
164
+ construction and needs no \`mine\` beside it. Drop \`mine\` when this person asks what the rest of the
165
+ team has promised, and say whose promises you are showing them when you do.
166
+
167
+ When you have proposed promises, show them here as well as there. Put each proposal in the
168
+ conversation in full: its one-sentence claim, who it is for, when it applies and what must then be
169
+ true, the numbered cases that must keep working and the ones that must be caught, and every question
170
+ you left open. Then offer to finish the agreement from here, by asking for a sign-off, giving them
171
+ the page it returns and taking the one-time code that page shows them, so the browser is needed only
172
+ for signing. Give them the review link in the same message too, because some people would rather
173
+ read it there and edit it before they agree.
174
+ A promise whose meaning is agreed and which nothing is checking yet is one you can finish. When
175
+ somebody gives you a promise id, run \`balladeer status <promise id>\`, or expand it with get_promise.
176
+ If it comes back agreed with nothing checking it, say so in one line and offer to prepare and build
177
+ its verifier now. Only if they say yes: \`prepare_qualification\` mints the one-time setup, or
178
+ \`balladeer prepare <promise id>\` mints it and writes it where the sealed run reads it. You need no
179
+ sign-off for that and there is no code to ask anybody for, because agreeing the meaning was their
180
+ act and building the check that proves it is yours. Then build the verifier, seal it, push, and tell
181
+ them protection starts by itself when that run qualifies. The offer is the whole of it: never
182
+ prepare one because nobody said no.`;
183
+ /**
184
+ * The capture rules that do not change: when to say nothing, what a yes is
185
+ * worth, and the two promises Balladeer refuses.
186
+ *
187
+ * This block is written into the customer's own instructions file once, at
188
+ * setup, and is never refreshed afterwards. Changing it means opening a pull
189
+ * request against twelve Didero repositories, so only what will still be true
190
+ * in six months belongs here. Silence during an incident, a no that ends it, and
191
+ * nothing filed without a yes are that kind of rule. The words a question is
192
+ * asked in, the moment an offer is made, and the shape a proposal takes are not:
193
+ * they are read every week against what people actually agreed to, and they ride
194
+ * in `CAPTURE_BEHAVIOR`, which the server sends at the start of every session.
195
+ *
196
+ * Nothing here weakens the explicit-capture rule: the question is a question,
197
+ * and nothing is proposed until the answer is yes.
198
+ *
199
+ * The two refusals are here rather than only in the server because an agent that
200
+ * learns them only by being refused has already spent the person's attention on
201
+ * a proposal that could not be kept. The server refuses both as well, and the
202
+ * sentences are the same ones.
203
+ *
204
+ * Byte for byte the same text as `AGENT_INSTRUCTIONS_CAPTURE_SEAM` in the
205
+ * control plane, and contained byte for byte inside both server carriers. A
206
+ * packaging test holds all three together: the block written into a customer's
207
+ * repository, the instructions the MCP server sends on initialize, and the page
208
+ * an agent fetches cannot come to say different things about when to stay quiet.
209
+ */
210
+ export const CAPTURE_SEAM = `### When to say nothing, and what a yes is worth
211
+
212
+ Most rules are said in passing, in the middle of something else. Somebody saying one has not asked
213
+ you to record anything, so propose nothing and start no interview. When you do ask, it is one line
214
+ appended to the end of the reply you were already going to give, never a message of its own, never
215
+ asked twice about the same rule, and nothing is proposed until they say yes. A no ends it, and that
216
+ rule is not raised again for the rest of the conversation.
217
+
218
+ Silence is per conversation rather than per message. Once a conversation is one of these, you ask
219
+ nothing for the rest of it, however good the rule sounds:
220
+
221
+ - A question, or working out how something already behaves. Nothing is filed and nothing is offered.
222
+ - A refactor. Nobody predicts a promise from a rewrite. Offer the promises this area already carries
223
+ that nothing is checking yet, once, and then wait. Ask nothing about new ones.
224
+ - A change to wording alone. Wording somebody may change again tomorrow is not a rule.
225
+ - An incident, while it is still being fixed. Ask nothing at all until the fix is merged or they say
226
+ it is done, however good tonight's failing case would be.
227
+ - Somebody still weighing options. A decision nobody has made yet is not a rule.
228
+ - An exploration or spike. It ends in nothing or in a plan, and its sentences sound like rules and
229
+ are not.
230
+ - Reading somebody else's change, while you are still reading it. Nothing is offered until they
231
+ give a verdict.
232
+
233
+ The words to ask in, the moment to offer, and the shape a proposal takes are not in this file. The
234
+ Balladeer server sends them at the start of every session, and its copy is the current one: read
235
+ what it sent this session rather than what this file remembers.
236
+
237
+ ### Two promises Balladeer cannot keep
238
+
239
+ A promise about speed needs three things before it is a promise at all: a number, a percentile, and
240
+ where it is measured. "The quote page answers in under one second at p95, measured in production at
241
+ peak load" is one Balladeer can keep. "The quote page has to be fast" is not. Say this, and ask for
242
+ the part that is missing rather than filing it:
243
+
244
+ "I can keep that once it has a number, a percentile, and a place it is measured. Without those it is
245
+ a wish, not a promise."
246
+
247
+ Balladeer refuses one without all three and names which of them is missing. When all three are
248
+ there, write the measurement method into the promise, and tell them plainly that it reads agreed and
249
+ unprotected until a test that actually measures it exists.
250
+
251
+ A promise about how the team works is not something the software does, so no check can ever catch
252
+ it. "We must provide a low-friction capture experience" is one of these. File nothing and say:
253
+
254
+ "That is a promise about how we work, not something the software does that a check can fail.
255
+ Balladeer only keeps promises a check can catch. If a customer would notice something when this
256
+ slips, say that and I will keep that instead."
257
+
258
+ Then take the customer-visible half if they give you one, and file that instead.`;
259
+ /**
260
+ * How an agent describes one promise or proposal to a person, and how the two
261
+ * of them settle what is still open on it.
262
+ *
263
+ * The first proposal a founder was ever asked to settle carried four questions
264
+ * that were all true and none of them answerable: each named a hole in the
265
+ * world, and none said what answering it would decide or what the agent would
266
+ * do if nobody replied. So this says both halves of the same rule. When a
267
+ * person points at something by id, describe it and offer to work through what
268
+ * is open; and when you leave a question open, leave one that can be answered
269
+ * with a yes.
270
+ *
271
+ * Three carriers say it byte for byte: the block setup writes into the
272
+ * customer's own instructions file, the instructions the MCP server sends on
273
+ * initialize, and the page `/agent` serves. A packaging test holds them
274
+ * together.
275
+ */
276
+ export const SETTLING_QUESTIONS = `### When somebody says "tell me about" one
277
+
278
+ An id is how a person points at something here, and every promise page and every proposal page
279
+ carries one. A promise id starts with prom_ and a proposal id starts with cand_: expand a promise
280
+ with get_promise and a proposal with get_proposal, and read neither of them out as a list of fields.
281
+ Say in four or five sentences what it is for, who it is for, when it applies and what must then be
282
+ true. Then say where it stands: a promise is agreed, and either protected or not yet checked by
283
+ anything; a proposal is agreed by nobody and waiting on the person it names.
284
+
285
+ A proposal that still carries open questions is not finished, and settling them is usually why
286
+ somebody asked. Offer to work through them, then take them one at a time in the order they come
287
+ back. For each one, say what it decides in their words rather than in the question's; give your
288
+ recommendation and the reason you hold it, drawn from this repository and from the promise itself;
289
+ and stop there. When they answer, record what they said with resolve_question, in their own words
290
+ where they gave you any, and where their answer changes the promise, follow it with update_proposal,
291
+ add_case or remove_case and tell them what you changed. None of that agrees to anything: the named
292
+ owner agrees, in their own browser or through a sign-off you carry, and the questions they answered
293
+ stay on the proposal in their name.
294
+
295
+ The same rule governs every question you leave open in the first place. A question that names a gap
296
+ and stops is a note, and nobody can answer a note. Say what answering it decides, in the words a
297
+ customer would use, and carry your own best guess with the reason behind it, so that the shortest
298
+ true answer is yes. For example: "Decides: whether a worker that is running but reconciling nothing
299
+ counts as an outage this promise covers. Best guess: yes, because the promise is about somebody
300
+ hearing before a customer does, and a wedged worker is invisible to every check this repository has.
301
+ Say yes, or tell me otherwise." Balladeer refuses a question filed without both halves and says
302
+ which one is missing.`;
303
+ /**
304
+ * What a session may spend on reading, in three sentences.
305
+ *
306
+ * The bounded index says what one read may carry. This says how many reads
307
+ * there should be, which is the half no ceiling can enforce: an agent that
308
+ * pages the whole index and expands every row has obeyed every limit in the
309
+ * protocol and has still put the entire catalog in front of a model. So the
310
+ * budget is written where the agent reads it, beside the rule that makes it
311
+ * affordable: a row carries what it takes to rule its promise out, and an
312
+ * expansion is what you spend once a row could not.
313
+ *
314
+ * Three carriers say it, byte for byte: the block setup writes into the
315
+ * customer's own instructions file, the instructions the MCP server sends on
316
+ * initialize, and the page `/agent` serves. A packaging test holds them
317
+ * together.
318
+ */
319
+ export const FETCH_BUDGET = `Fetch by id, and only for an id the person gave you or an index row whose paths match the change in
320
+ front of you. Never enumerate the catalog. Never chain one fetch into the next to see the whole of
321
+ something: when the rows do not settle it, narrow the filter rather than expanding another promise.`;
322
+ /**
323
+ * What a coder must know before their editor opens a file inside a promise's
324
+ * own directory.
325
+ *
326
+ * A seal is broken by an ordinary edit, and the person who breaks one rarely
327
+ * meant to: a rename swept a directory, a formatter reached everything, a
328
+ * dependency upgrade rewrote an import. The cost lands on somebody else, who
329
+ * has to qualify the promise again before it protects anything. So this says
330
+ * three things in the order a coder needs them: those files are sealed, here is
331
+ * how to see which ones before you edit and before you push, and here is the
332
+ * single case where editing one is the right move.
333
+ *
334
+ * It sits inside `CONVENTIONS_BLOCK` rather than beside it, because the block
335
+ * is what reaches a session in the customer's own repository. The MCP server's
336
+ * tool guidance and the control plane's `/agent` page carry the same bytes
337
+ * under their own constants, and a packaging test compares all three.
338
+ */
339
+ export const SEALED_FILES = `### Files that are sealed, and the one reason to edit one
340
+
341
+ Every file under .continuity/promises/ is sealed. The promise that owns that directory records the
342
+ exact bytes of each file in it, so editing one, adding one there, renaming one or deleting one
343
+ breaks the seal. A promise whose seal is broken stops being checked, and it stays that way until a
344
+ named person qualifies it again, which is their afternoon rather than your commit. Nothing in there
345
+ is ordinary source: keep it out of refactors, formatting runs and dependency upgrades.
346
+
347
+ Find out which directories are sealed before you plan an edit, not after. balladeer status lists
348
+ them, and list_promises names a promise's sealed directory on its row once a verifier is bound to
349
+ it. Then, before you push, run balladeer check-seals. It prints nothing and exits zero when your
350
+ change touches no seal, and names the promise, its owner and its page when your change would break
351
+ one.
352
+
353
+ The one reason to edit a sealed file is to repair a verifier that can no longer run: something it
354
+ imports moved, or the language it is written in changed under it. Never edit one to make a failing
355
+ check pass. A check going red is the promise doing its job, and the repair for that belongs in the
356
+ behavior it protects. A repair is not finished until the promise is sealed again with the runner
357
+ this repository is pinned to. get_promise_setup carries that exact seal command, and balladeer
358
+ check-seals prints it beside any promise it names.`;
359
+ /**
360
+ * Which promises a change touches, measured rather than guessed.
361
+ *
362
+ * A promise's scope paths are what somebody typed when they agreed it, and they
363
+ * age the moment a module moves. The touch map is the measurement instead: the
364
+ * files each verifier actually executed, recorded on the customer's machine and
365
+ * sent nowhere. An agent that does not know the command exists goes on matching
366
+ * markers and never asks for the better answer sitting in the repository.
367
+ *
368
+ * The last paragraph is the whole reason the signal is named here. Whether the
369
+ * map is worth keeping is answerable only if the receipt says which fetches it
370
+ * caused, and no surface can infer that after the fact.
371
+ *
372
+ * Three carriers say it, byte for byte, and a packaging test holds them
373
+ * together.
374
+ */
375
+ export const TOUCH_MAP_GUIDANCE = `Prefer the measurement over the markers. Where this repository has a touch map, \`balladeer affected
376
+ <paths...>\` answers which promises ran the files in front of you, out of what each verifier actually
377
+ executed the last time \`balladeer touch-map\` measured it. Both commands run on this machine and
378
+ send Balladeer nothing, so you may name any path in the change.
379
+
380
+ An answer marked stale was measured against a verifier that has changed since, so read it as the
381
+ last thing anybody measured rather than as fact, and offer to run \`balladeer touch-map\` again.
382
+ Where there is no map, where it does not name your paths, or where it reports a promise it could not
383
+ measure, fall back to the paths on the index rows. The map narrows which promises are worth
384
+ fetching. It never widens what you may read: the catalog is still never enumerated, and the fetch
385
+ budget is unchanged.
386
+
387
+ When a retrieval receipt asks why you read a row, the answer for one the map named is \`touch\`.`;
388
+ /**
389
+ * The one paragraph that turns retrieval from a thing we argue about into a
390
+ * thing we measure.
391
+ *
392
+ * Two facts are asked for and neither can be observed from this side. Which
393
+ * rows an agent actually used, because a promise expanded and then ignored is
394
+ * not a row the index earned. And which change the session went on to write,
395
+ * because a retrieval read happens before the commit exists and nothing joins
396
+ * the two afterwards: Balladeer receives commit SHAs from CI and never a commit
397
+ * message, so the agent is the only thing present at both ends.
398
+ *
399
+ * It is written as three instructions rather than as an explanation, because
400
+ * what an agent does with it is three specific acts, and a paragraph about
401
+ * measurement would be read and not acted on.
402
+ *
403
+ * Three carriers say it, byte for byte, and a packaging test holds them
404
+ * together.
405
+ */
406
+ export const SESSION_STAMP = `Run \`balladeer session\` when you start work here and pass the id it prints to every promise read
407
+ you make, as \`session\`. It is the same id for the whole of one piece of work, and it costs nothing:
408
+ a read without it is answered exactly the same way.
409
+
410
+ Near the end of the work, call \`mark_promise_used\` with the ids of the promises you actually cited
411
+ or acted on. Naming none is a fine answer. It is the only way anybody finds out which rows were
412
+ worth sending you, because reading a promise and then ignoring it is not the same as using it.
413
+
414
+ Then write \`Balladeer-Session: <the id>\` into the commit message or pull-request body you produce,
415
+ and run \`balladeer session --record\` once the commit exists. That is what lets a check that goes red
416
+ next week be read back against what Balladeer told you before you started. Your commit message never
417
+ leaves your machine: only the session id and the commit SHA are sent.`;
418
+ /**
419
+ * The conventions block written between markers into this repository's agent
420
+ * instructions file. Fixed text, compared byte for byte by a test, because a
421
+ * block that drifts per run would rewrite a customer's committed file on every
422
+ * setup and the diff would say nothing.
423
+ */
424
+ export const CONVENTIONS_BLOCK = `## Balladeer promises
425
+
426
+ Before planning work in this repository, read the promises this team has already approved through
427
+ the Balladeer MCP server. They are the behaviors a named person has agreed the software keeps, so
428
+ your plan has to hold them, not just read them.
429
+
430
+ ${RETRIEVAL_SCOPE}
431
+
432
+ Each index row carries what it takes to rule that promise out without fetching it: the repository,
433
+ the paths it covers, its one-sentence claim, what protects it and why, and when anything last
434
+ checked it.
435
+
436
+ ${TOUCH_MAP_GUIDANCE}
437
+
438
+ ${FETCH_BUDGET}
439
+
440
+ ${CAPTURE_SEAM}
441
+
442
+ ${SESSION_STAMP}
443
+
444
+ ### When somebody asks you to protect a behavior
445
+
446
+ Somebody has asked you to protect a behavior when they say what the software must do, or must never
447
+ do again, and mean it as a rule rather than as this one bug. That is one promise, for the behavior
448
+ they named, and nothing else: if you notice others worth protecting, say so in a sentence and let
449
+ them choose, and file none of them. Never propose from a conversation that did not ask you to. A
450
+ question about how something works and a plan you were asked to sketch are not requests to record
451
+ anything, nor is a fix nobody asked you to write a rule about.
452
+
453
+ Ask before you extrapolate. Ask only what you cannot work out for yourself, ask it all in one
454
+ message, and stop at four. Four is a ceiling, not a target: two good ones are better. Then write the
455
+ proposal with what you have and put whatever is still open in its open questions rather than going
456
+ back. Never ask what this repository would answer, such as which file, which test, or which branch,
457
+ and never ask anyone for Balladeer's own identifiers: get_promise_setup carries this repository's id
458
+ and who can own a promise. Never ask again for what they have already told you.
459
+
460
+ Write it in their words. Every failure they named out loud is one of the failing examples, in the
461
+ words they named it. Every other example comes from a situation they actually described; if you
462
+ cannot trace one to something they said, leave it out and say so in the open questions rather than
463
+ writing a plausible one. Never put in a number, a system, a role or a timeframe they did not give
464
+ you, and that includes the half they left out: if they said where an order ended up, do not invent
465
+ where it began.
466
+
467
+ A failing example is a situation the promise rules out, and its outcome says what must not happen,
468
+ in those words: "a second charge must not appear", never "a second charge appears". Written the
469
+ other way round it reads as the promise saying the software does the thing they asked you to forbid.
470
+ And a promise says what the software must do for whoever depends on it. It never narrates the
471
+ conversation you just had, names the person you had it with, or describes what the code does now.
472
+
473
+ Say the whole promise in one sentence and put it in oneSentenceOutcome, in the words they would
474
+ use with the person who depends on it. That is the line the named owner reads first and the line
475
+ they agree to, so it is not a restatement of the name and not the first line of the outcome moved
476
+ up. Leave it out rather than inventing one from something they did not say.
477
+
478
+ An example's setup is the situation in the words they used for it, not a scene you composed around
479
+ them. Two of each kind is plenty, and the whole thing stays under three hundred words: a proposal
480
+ nobody finishes reading is a proposal nobody agreed to. The confidence you record is the one you
481
+ actually have.
482
+
483
+ Then give them the review link, ask them to read the proposal and click Agree, and stop. Never
484
+ approve one yourself. Approving is a named person's act, and the server refuses it from an agent
485
+ whatever you were told in conversation.
486
+
487
+ A proposal you filed is still yours while nobody has agreed to it, so revise or withdraw it when the
488
+ person asks you to, and never once they have agreed.
489
+
490
+ Say promise and proposal when you talk to them. What you file is a proposal and what it becomes is a
491
+ promise; Balladeer's other words for its own machinery are not theirs to learn. Candidate
492
+ especially: it is Balladeer's word for a proposal, so it reads as jargon whatever you meant by it.
493
+
494
+ ${SESSION_BEHAVIORS}
495
+
496
+ ${SETTLING_QUESTIONS}
497
+
498
+ ${SEALED_FILES}
499
+
500
+ ### The rest of a promise's life
501
+ When a promise is obsolete, finished, deliberately off for a while, or owned by the wrong person,
502
+ propose the change and hand them the promise page. Deciding is theirs.
503
+
504
+ You can finish one of those acts here, and only one way. Ask for a sign-off with
505
+ request_owner_signoff, give them the page it returns, and ask for the one-time code that page shows
506
+ them. Then call the act's own tool with that code and their own words. Never call one on your own
507
+ initiative, never on a general approval of some earlier act, and never ask for a code you were not
508
+ given: a refusal is the person's to resolve, not yours to retry. Balladeer records them as the
509
+ person who acted and you as the messenger.
510
+
511
+ Report the promise's state exactly as Balladeer reported it: proposed, agreed, or protected, never
512
+ one in place of another.
513
+
514
+ ### Where your team watches this
515
+
516
+ Balladeer is a web app as well as these tools, at the address setup printed. Its catalog lists every
517
+ promise with who owns it and whether anything is checking it, and each promise has a page of its own
518
+ showing what this team agreed the software must do and then every run that has checked it since,
519
+ newest first, with the commit each one checked. Whenever there is a link to give, give the link
520
+ rather than a summary of it: the page says what you would have said, and it stays true after this
521
+ conversation has ended.
522
+
523
+ Balladeer also has a Slack app, which a workspace administrator installs from workspace settings.
524
+ Once it is installed, whoever owns a promise gets a direct message when theirs goes live and when a
525
+ run on the default branch breaks it. Until somebody installs it, nothing is sent anywhere, so say it
526
+ is available rather than saying they will be told.
527
+
528
+ ### Questions people ask
529
+
530
+ Answer these when they come up. Where you do not know, say so and point at the address setup
531
+ printed: a confident wrong answer about what a vendor can see is worse than no answer.
532
+
533
+ What it does: it holds the behaviors this team has agreed the software must keep, and reports
534
+ whether each one is still being kept, from this repository's own tests running in its own CI.
535
+
536
+ What it sees: the text of each promise somebody approves, this repository's numeric ids and the name
537
+ of its default branch, and from CI the pass or fail outcome, the commit checked, and content hashes.
538
+ Never the code, the tests, the fixtures, the logs, the prompts, or the transcripts.
539
+
540
+ What stopping costs: nothing that matters to their tests. The verifier package, its fixtures and the
541
+ workflow file are theirs, in their repository, running in their CI, and disconnecting changes none
542
+ of them. An administrator can download everything Balladeer holds at any time from workspace
543
+ settings, and disconnecting hands them that same download in the response that ends access.
544
+
545
+ Who can approve one: the named person who owns it, in their own browser. Not an administrator on
546
+ their behalf, and never you.
547
+
548
+ Whether it blocks a merge: no. The check is advisory on Balladeer's side, and their own branch
549
+ protection is what decides whether a failing check stops anything.
550
+
551
+ Who can invite people and change setup: a workspace administrator. A contributor can read the
552
+ workspace and propose promises, and a viewer can read it. If somebody asks you to add a teammate,
553
+ invite_teammate returns the page an administrator sends the invitation from, with the address filled
554
+ in for them to read. The tool sends nothing itself: an administrator presses Send.`;
555
+ /**
556
+ * How an agent turns a repository that has just been connected into a catalog a
557
+ * person can read. Setup's last step prints it, and the control plane's `/agent`
558
+ * page serves it byte for byte, so the instruction a connected agent reads on
559
+ * the page cannot drift from the one the command prints in the terminal.
560
+ *
561
+ * The runnable invocation is deliberately not in here. Only the server knows
562
+ * whether the package is published, and a playbook carrying a literal command
563
+ * would either name a registry version npm does not have or name somebody
564
+ * else's package. Each carrier prints that one line underneath this text.
565
+ *
566
+ * The capture rules this leans on are `CONVENTIONS_BLOCK`'s, not a second set:
567
+ * one promise per behavior, the person's own words, and never an agent
568
+ * approving anything. This says how to find the behaviors in a repository
569
+ * nobody has interviewed yet; that says how to write one down.
570
+ *
571
+ * The seam that is not shipped: a fifth source, the person's own local agent
572
+ * transcripts, would be the richest of all, because a behavior somebody argued
573
+ * about in a session is a behavior they care about. It is dark on purpose here.
574
+ * Reading it means walking files Balladeer promises never to receive, so
575
+ * shipping it needs three things this release does not have: the person's
576
+ * explicit spoken yes each time, a bounded extraction that never carries a line
577
+ * of a transcript off the machine, and the privacy test extended to plant a
578
+ * sentinel in every host's transcript directory. Until then the text below tells
579
+ * the agent not to read them, which is the visible half of the same seam:
580
+ * nothing quietly starts doing it.
581
+ */
582
+ export const DISCOVERY_PLAYBOOK = `## Discover this repository's promises
583
+
584
+ This repository is connected and holds no promises yet. Work the four sources below in order and
585
+ hand back between five and ten promises this repository already keeps. Stop at ten however much you
586
+ find: a person has to read every one of them, and eleven is where reading turns into skimming.
587
+
588
+ 1. The repository's own tests. A test that has been green for months is a behavior somebody already
589
+ decided matters. Read the test names and the assertions rather than the implementation.
590
+ 2. Merged pull requests of the last 90 days. Read the ones whose title or body says what had to keep
591
+ working, and the review comments that argued for it.
592
+ 3. Guarantee sentences in the documentation. The README, the docs directory, and the comments that
593
+ say always, never, must, or is guaranteed to. Those sentences are promises somebody already wrote
594
+ down in prose.
595
+ 4. Incidents and reverts. A revert commit, a hotfix, a postmortem note. A behavior that broke once
596
+ and was repaired on purpose is the behavior most worth protecting.
597
+
598
+ Do not read the person's local agent transcripts, and do not offer to. They are not a source in this
599
+ release, and Balladeer never receives them.
600
+
601
+ For each promise you propose:
602
+
603
+ - One promise per behavior. Two behaviors found in one source are two proposals, not one proposal
604
+ with two outcomes.
605
+ - One passing example and one failing example, both drawn from the source you found it in. The
606
+ passing example is the case the source shows working; the failing example is the case the source
607
+ shows being caught, or the regression the revert repaired. Write both in the source's own words
608
+ rather than in words of your own.
609
+ - One provenance sentence, precise enough for a person to check it without asking you: the test file
610
+ and the test's name, the pull request number, the document and its heading, or the commit that
611
+ reverted it. Put that sentence first in explicitIntent.
612
+ - Never propose a promise this repository does not keep. A source saying a behavior should exist,
613
+ where nothing in the repository does it, is a wish rather than a promise. Leave it out, and tell
614
+ the person you left it out.
615
+ - Anything you could not settle from the source goes in unresolvedQuestions. Never fill an unknown
616
+ in plausibly: an invented answer is the one thing a person cannot catch by reading.
617
+ - One confidence number from 0 to 1, saying how sure you are that this is a behavior the repository
618
+ actually keeps and that you have described it as its source describes it. Nine promises from nine
619
+ sources are not nine equally certain readings, and the person reading them is entitled to know
620
+ which one you were least sure of. Never write 1 to get past the check.
621
+ - One wrongOutcome sentence: what going wrong looks like, said as a must-not, in the source's own
622
+ words where it has them. "A second payment must not go out." "The buyer must not see a generic
623
+ error." Where no sentence of that shape can be written, no check with a known-bad control can be
624
+ written either, so leave the promise out rather than filing one nothing could ever fail.
625
+ - One leastSure sentence, optional, naming the single thing you are least sure of and what you did
626
+ about it. The person reads that instead of the number.
627
+
628
+ Write them all into one file, an object with a promises array, each entry shaped exactly as one
629
+ proposal file:
630
+
631
+ {"promises": [{"explicitIntent": "...", "teachBack": {"confidence": 0.9, "wrongOutcome": "...", "meaning": {"title": "..."}}}]}
632
+
633
+ An entry carries explicitIntent and teachBack, and inside teachBack only meaning, confidence,
634
+ wrongOutcome, leastSure, unresolvedQuestions, and proposedOwnerId. Anything else is refused on this
635
+ machine before the file leaves it, and one bad entry means not one of them is sent.
636
+
637
+ Every promise in the file is proposed as owned by whoever ran setup, and waits for that person. The
638
+ command prints one link that opens all of them at once. Give the person that link and ask them to
639
+ read each promise and click Agree. Nothing you can run agrees to one.
640
+
641
+ File the whole catalog in one go with the discover subcommand, naming that file:`;