agentbox-app 0.1.7 → 0.1.12
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/README.md +220 -58
- package/bin/agentbox.mjs +18 -3
- package/briefs/message-rules.md +24 -3
- package/briefs/worker.md +63 -49
- package/briefs/writing-rules.md +90 -131
- package/main/account-discovery.mjs +21 -20
- package/main/account-tooling.mjs +11 -11
- package/main/agent-activity.mjs +45 -5
- package/main/agent-schedule.mjs +14 -14
- package/main/agent-sessions.mjs +94 -10
- package/main/agent-updates.mjs +116 -0
- package/main/agents.mjs +52 -46
- package/main/analytics.mjs +27 -0
- package/main/approval-prompt-server.mjs +2 -2
- package/main/approvals.mjs +14 -5
- package/main/artifact-path.mjs +11 -0
- package/main/claude-bin.mjs +32 -5
- package/main/claude-input.mjs +45 -3
- package/main/claude-plan.mjs +25 -13
- package/main/code-change.mjs +3 -3
- package/main/codex-account.mjs +1 -1
- package/main/codex-bin.mjs +18 -0
- package/main/codex-launch-env.mjs +31 -0
- package/main/codex-memory-gate.mjs +260 -0
- package/main/codex-models.mjs +12 -7
- package/main/codex-threads.mjs +46 -23
- package/main/codex-usage-file.mjs +7 -7
- package/main/codex-usage.mjs +4 -4
- package/main/codex-watch.mjs +12 -12
- package/main/config.mjs +82 -17
- package/main/demo.mjs +17 -14
- package/main/dev-window.mjs +9 -9
- package/main/doc-scheme.mjs +2 -0
- package/main/engine-setup.mjs +204 -0
- package/main/feedback.mjs +55 -0
- package/main/folder-pictures.mjs +48 -0
- package/main/frame-scrollbars.mjs +90 -0
- package/main/fresh-user.mjs +7 -4
- package/main/git-change-offthread.mjs +70 -0
- package/main/git-change-thread.mjs +11 -0
- package/main/git-change.mjs +9 -3
- package/main/img-scheme.mjs +70 -1
- package/main/instruction-settings.mjs +134 -60
- package/main/ipc.mjs +335 -42
- package/main/leftovers.mjs +518 -0
- package/main/live-replies.mjs +43 -5
- package/main/machine.mjs +48 -1
- package/main/main.mjs +138 -15
- package/main/memory-gate-history.mjs +254 -0
- package/main/memory-gate-server.mjs +461 -0
- package/main/memory-gate.mjs +206 -0
- package/main/message-priority.mjs +87 -0
- package/main/notify.mjs +1 -1
- package/main/rail-note.mjs +2 -2
- package/main/refresh-agent-models.mjs +21 -0
- package/main/repeats.mjs +4 -4
- package/main/row-label.mjs +115 -51
- package/main/runs-on.mjs +93 -0
- package/main/serve.mjs +77 -5
- package/main/settings.mjs +245 -26
- package/main/ship-queue.mjs +279 -0
- package/main/sign-in-files.mjs +39 -0
- package/main/source-updater.mjs +298 -0
- package/main/store/home.mjs +84 -7
- package/main/store/project.mjs +15 -19
- package/main/store/work-items.mjs +150 -6
- package/main/store.mjs +245 -13
- package/main/supervisor.mjs +1634 -417
- package/main/task-commands.mjs +8 -10
- package/main/task-folders.mjs +94 -16
- package/main/task-remote-control.mjs +3 -3
- package/main/task-terminals.mjs +14 -2
- package/main/team/index.mjs +440 -0
- package/main/team/memory-cloud.mjs +247 -0
- package/main/team/projects.mjs +162 -0
- package/main/team/session.mjs +225 -0
- package/main/team/sign-in.mjs +106 -0
- package/main/team/supabase-backend.mjs +231 -0
- package/main/team/sync.mjs +163 -0
- package/main/updater.mjs +15 -5
- package/main/write-before-reload.mjs +50 -0
- package/mcp/core/page.mjs +10 -12
- package/mcp/core/work.mjs +123 -26
- package/mcp/tools.mjs +13 -6
- package/package.json +21 -9
- package/renderer/dist/assets/agentbox-icon-F1oN9nj_.svg +15 -0
- package/renderer/dist/assets/index-ChKsQkRw.js +1169 -0
- package/renderer/dist/assets/index-ClBXnq3B.css +32 -0
- package/renderer/dist/index.html +2 -2
- package/scripts/after-install.mjs +14 -0
- package/scripts/approval-server.sh +7 -2
- package/scripts/memory-gate-hook.sh +59 -0
- package/shared/agent-import.mjs +39 -16
- package/shared/agents.d.mts +26 -8
- package/shared/agents.mjs +100 -108
- package/shared/analytics-events.mjs +19 -2
- package/shared/answers.mjs +12 -0
- package/shared/bridge-map.d.mts +12 -0
- package/shared/bridge-map.mjs +38 -1
- package/shared/claude-commands.generated.mjs +2 -2
- package/shared/claude-models.generated.mjs +6 -6
- package/shared/claude-usage.mjs +6 -6
- package/shared/codex-import.mjs +7 -7
- package/shared/codex-modes.d.mts +50 -0
- package/shared/codex-modes.mjs +1 -1
- package/shared/codex-usage.mjs +7 -8
- package/shared/demo-world.mjs +6 -6
- package/shared/engines.mjs +27 -10
- package/shared/feedback.d.mts +14 -0
- package/shared/feedback.mjs +44 -0
- package/shared/first-run-examples.mjs +4 -4
- package/shared/first-run-practice.d.mts +16 -0
- package/shared/first-run-practice.mjs +176 -70
- package/shared/fresh-user-home.mjs +34 -4
- package/shared/instruction-defaults.json +2 -2
- package/shared/product-name.mjs +4 -2
- package/shared/project-folder-check.mjs +9 -3
- package/shared/rank.d.mts +1 -0
- package/shared/rank.mjs +22 -0
- package/shared/referenced-files.mjs +1 -1
- package/shared/runs-on.d.mts +20 -0
- package/shared/runs-on.mjs +79 -0
- package/shared/schemes.d.mts +11 -0
- package/shared/schemes.mjs +1 -1
- package/shared/shortcuts.d.mts +41 -0
- package/shared/shortcuts.mjs +236 -0
- package/shared/spawn-trouble.d.mts +2 -0
- package/shared/spawn-trouble.mjs +40 -19
- package/shared/team-rules.d.mts +17 -0
- package/shared/team-rules.mjs +230 -0
- package/shared/team-status.d.mts +11 -0
- package/shared/team-status.mjs +90 -0
- package/shared/terminal-links.d.mts +2 -0
- package/shared/terminal-links.mjs +55 -0
- package/shared/terminal-state.d.mts +1 -0
- package/shared/terminal-state.mjs +16 -0
- package/shared/thread-cards.d.mts +19 -0
- package/shared/thread-cards.mjs +254 -0
- package/shared/usage.d.mts +1 -1
- package/shared/usage.mjs +6 -7
- package/shared/work-items.mjs +258 -28
- package/shared/work-lines.mjs +393 -16
- package/worker-permissions.json +1 -1
- package/renderer/dist/assets/cel-dusk-CS5I7kJS.webp +0 -0
- package/renderer/dist/assets/cel-dusk-DUslqS6B.webp +0 -0
- package/renderer/dist/assets/cel-dusk-Jt_xVGxp.webp +0 -0
- package/renderer/dist/assets/cel-dusk-sm-BBkV-tWT.webp +0 -0
- package/renderer/dist/assets/frost-haze-CxPSOBEg.webp +0 -0
- package/renderer/dist/assets/frost-haze-sm-C_w21qgd.webp +0 -0
- package/renderer/dist/assets/ice-BC8luINc.webp +0 -0
- package/renderer/dist/assets/ice-CP9PrKHo.webp +0 -0
- package/renderer/dist/assets/ice-river-D6ziOhLY.webp +0 -0
- package/renderer/dist/assets/ice-river-UVM2-JY_.webp +0 -0
- package/renderer/dist/assets/ice-river-bErJwYWW.webp +0 -0
- package/renderer/dist/assets/ice-river-sm-Bg1U-SIj.webp +0 -0
- package/renderer/dist/assets/ice-sm-CbVcg3_D.webp +0 -0
- package/renderer/dist/assets/index-B7hhfHrT.js +0 -684
- package/renderer/dist/assets/index-CwiDv5bL.css +0 -32
- package/renderer/dist/assets/lake-C0WaW-6E.webp +0 -0
- package/renderer/dist/assets/lake-CSKjLC5K.webp +0 -0
- package/renderer/dist/assets/lake-ETGcOb25.webp +0 -0
- package/renderer/dist/assets/lake-harbour-BCQRbrHb.webp +0 -0
- package/renderer/dist/assets/lake-harbour-B_wfXTmE.webp +0 -0
- package/renderer/dist/assets/lake-harbour-Te1pEvBh.webp +0 -0
- package/renderer/dist/assets/lake-harbour-sm-Cme_ShEg.webp +0 -0
- package/renderer/dist/assets/lake-sm-CbG72Hbv.webp +0 -0
- package/renderer/dist/assets/lino-coast-CUZHcucI.webp +0 -0
- package/renderer/dist/assets/lino-coast-DP4J7cgd.webp +0 -0
- package/renderer/dist/assets/lino-coast-kOIAffr_.webp +0 -0
- package/renderer/dist/assets/lino-coast-sm-C1Mdbgit.webp +0 -0
- package/renderer/dist/assets/moon-pines-BskgnnXR.webp +0 -0
- package/renderer/dist/assets/moon-pines-CFSIIwt0.webp +0 -0
- package/renderer/dist/assets/moon-pines-PNhdOYww.webp +0 -0
- package/renderer/dist/assets/moon-pines-sm-C6K1NomK.webp +0 -0
- package/renderer/dist/assets/orbit-rings-2XV36Ch3.webp +0 -0
- package/renderer/dist/assets/orbit-rings-C4NrcYGQ.webp +0 -0
- package/renderer/dist/assets/orbit-rings-DGLk07dT.webp +0 -0
- package/renderer/dist/assets/orbit-rings-sm-Dky3YdvL.webp +0 -0
- package/renderer/dist/assets/peach-haze-2-C6f7xnWw.webp +0 -0
- package/renderer/dist/assets/peach-haze-2-sm-Dj_Ez_Sb.webp +0 -0
- package/renderer/dist/assets/pixel-harbour-DQjqMROg.webp +0 -0
- package/renderer/dist/assets/pixel-harbour-Dw71H_bc.webp +0 -0
- package/renderer/dist/assets/pixel-harbour-kOZfm-GM.webp +0 -0
- package/renderer/dist/assets/pixel-harbour-sm-Dturjuky.webp +0 -0
- package/renderer/dist/assets/pixel-orbit-C296JVMO.webp +0 -0
- package/renderer/dist/assets/pixel-orbit-C4oMRDSx.webp +0 -0
- package/renderer/dist/assets/pixel-orbit-CqVmQ4eh.webp +0 -0
- package/renderer/dist/assets/pixel-orbit-sm-CHagC_nO.webp +0 -0
- package/renderer/dist/assets/pixel-ridge-C6LYu6uE.webp +0 -0
- package/renderer/dist/assets/pixel-ridge-CIUCEESs.webp +0 -0
- package/renderer/dist/assets/pixel-ridge-sm-BnE0F_w-.webp +0 -0
- package/renderer/dist/assets/riso-hills-7heKVtry.webp +0 -0
- package/renderer/dist/assets/riso-hills-CIjAL3J6.webp +0 -0
- package/renderer/dist/assets/riso-hills-sm-DHsnbCfP.webp +0 -0
- package/renderer/dist/assets/slate-haze-BPWdkNsw.webp +0 -0
- package/renderer/dist/assets/slate-haze-sm-B0Cb5a2W.webp +0 -0
- package/renderer/dist/assets/valley-haze-BDHPqoJy.webp +0 -0
- package/renderer/dist/assets/valley-haze-sm-CTyjmPAG.webp +0 -0
- package/renderer/dist/assets/vector-dunes-DzzWLdKo.webp +0 -0
- package/renderer/dist/assets/vector-dunes-Yr9NBQUy.webp +0 -0
- package/renderer/dist/assets/vector-dunes-sm-D8MYY6ms.webp +0 -0
- package/renderer/dist/assets/watercolour-mist-BCGKN4u4.webp +0 -0
- package/renderer/dist/assets/watercolour-mist-BF-jk5MC.webp +0 -0
- package/renderer/dist/assets/watercolour-mist-sm-Ds1xzTw9.webp +0 -0
- package/renderer/dist/assets/woodblock-sea-B1um67Z9.webp +0 -0
- package/renderer/dist/assets/woodblock-sea-DKQdYs32.webp +0 -0
- package/renderer/dist/assets/woodblock-sea-sm-BJzNq8xh.webp +0 -0
- package/renderer/dist/emulator/audio-rules.mjs +0 -74
- package/renderer/dist/emulator/data/compression/README.md +0 -11
- package/renderer/dist/emulator/data/compression/extract7z.js +0 -1
- package/renderer/dist/emulator/data/compression/extractzip.js +0 -1
- package/renderer/dist/emulator/data/compression/libunrar.js +0 -519
- package/renderer/dist/emulator/data/compression/libunrar.wasm +0 -0
- package/renderer/dist/emulator/data/cores/README.md +0 -22
- package/renderer/dist/emulator/data/cores/mgba-legacy-wasm.data +0 -0
- package/renderer/dist/emulator/data/cores/mgba-thread-legacy-wasm.data +0 -0
- package/renderer/dist/emulator/data/cores/mgba-thread-wasm.data +0 -0
- package/renderer/dist/emulator/data/cores/mgba-wasm.data +0 -0
- package/renderer/dist/emulator/data/cores/package.json +0 -65
- package/renderer/dist/emulator/data/cores/reports/mgba.json +0 -1
- package/renderer/dist/emulator/data/emulator.css +0 -1614
- package/renderer/dist/emulator/data/loader.js +0 -170
- package/renderer/dist/emulator/data/localization/README.md +0 -63
- package/renderer/dist/emulator/data/localization/af-FR.json +0 -339
- package/renderer/dist/emulator/data/localization/ar-AR.json +0 -301
- package/renderer/dist/emulator/data/localization/ben-BEN.json +0 -301
- package/renderer/dist/emulator/data/localization/de-GER.json +0 -301
- package/renderer/dist/emulator/data/localization/el-GR.json +0 -301
- package/renderer/dist/emulator/data/localization/en-US.json +0 -339
- package/renderer/dist/emulator/data/localization/es-ES.json +0 -310
- package/renderer/dist/emulator/data/localization/fa-AF.json +0 -310
- package/renderer/dist/emulator/data/localization/hi-HI.json +0 -301
- package/renderer/dist/emulator/data/localization/it-IT.json +0 -302
- package/renderer/dist/emulator/data/localization/ja-JA.json +0 -301
- package/renderer/dist/emulator/data/localization/jv-JV.json +0 -301
- package/renderer/dist/emulator/data/localization/ko-KO.json +0 -336
- package/renderer/dist/emulator/data/localization/pt-BR.json +0 -361
- package/renderer/dist/emulator/data/localization/retroarch.json +0 -617
- package/renderer/dist/emulator/data/localization/ro-RO.json +0 -310
- package/renderer/dist/emulator/data/localization/ru-RU.json +0 -301
- package/renderer/dist/emulator/data/localization/tr-TR.json +0 -310
- package/renderer/dist/emulator/data/localization/vi-VN.json +0 -302
- package/renderer/dist/emulator/data/localization/zh-CN.json +0 -351
- package/renderer/dist/emulator/data/src/GameManager.js +0 -464
- package/renderer/dist/emulator/data/src/compression.js +0 -142
- package/renderer/dist/emulator/data/src/emulator.js +0 -6158
- package/renderer/dist/emulator/data/src/gamepad.js +0 -167
- package/renderer/dist/emulator/data/src/nipplejs.js +0 -1
- package/renderer/dist/emulator/data/src/shaders.js +0 -236
- package/renderer/dist/emulator/data/src/socket.io.min.js +0 -7
- package/renderer/dist/emulator/data/src/storage.js +0 -125
- package/renderer/dist/emulator/data/version.json +0 -5
- package/renderer/dist/emulator/host.js +0 -299
- package/renderer/dist/emulator/index.html +0 -28
- package/renderer/dist/emulator/provenance.json +0 -6
|
@@ -5,10 +5,10 @@
|
|
|
5
5
|
// of the walk. What tells somebody it is not theirs is a band across the top
|
|
6
6
|
// that never leaves, not the size of it.
|
|
7
7
|
//
|
|
8
|
-
// WHY IT EXISTS AT ALL is
|
|
9
|
-
// saw a real task on a real screen and read it as work.
|
|
10
|
-
// thought the task was to set up the project and that it was asking
|
|
11
|
-
// questions to do the setup, and
|
|
8
|
+
// WHY IT EXISTS AT ALL is a tester, on a call of 2026-08-23: they opened Agentbox,
|
|
9
|
+
// saw a real task on a real screen and read it as work. Their words were that they
|
|
10
|
+
// thought the task was to set up the project and that it was asking them
|
|
11
|
+
// questions to do the setup, and they tried to answer the placeholder text.
|
|
12
12
|
//
|
|
13
13
|
// Everything here is content, no window and no filesystem, so both halves can
|
|
14
14
|
// read it: the renderer draws the walk off ../renderer/src/onboarding.ts and
|
|
@@ -63,9 +63,19 @@ export const PRACTICE_FLAG = 'practice';
|
|
|
63
63
|
* what she reads at beat ten is these two paragraphs together, under the
|
|
64
64
|
* practice band and over a "Start it ⌘↵" button. They have to make sense as
|
|
65
65
|
* one card, which is why the body opens by naming the app the title names. */
|
|
66
|
+
// EVERYDAY WORK, NOT CODE (2026-10-01). It was a sign-out button for a pretend
|
|
67
|
+
// app, and the four rows below were a sign-in route, a flaky test, a slow CI run
|
|
68
|
+
// and dead code. A persona test of an executive assistant found all of it
|
|
69
|
+
// written for programmers. A meeting summary, a reply, a tidy list, a budget and a
|
|
70
|
+
// date are work everybody on a team does, engineers included.
|
|
71
|
+
// AND THE BODY IS WHAT A PERSON WOULD TYPE (2026-10-06). It read "Practice is a
|
|
72
|
+
// pretend project, not your work and not Agentbox. This one is written for you
|
|
73
|
+
// already.", which is the walk talking to her, and it was then drawn in her
|
|
74
|
+
// own thread as a message from "You". The band over the window already says
|
|
75
|
+
// none of it is hers.
|
|
66
76
|
export const PRACTICE_TASK = {
|
|
67
|
-
title: 'Add a
|
|
68
|
-
body:
|
|
77
|
+
title: 'Add a summary to the Practice meeting notes.',
|
|
78
|
+
body: 'Keep it short: what we decided, and what is still open.',
|
|
69
79
|
};
|
|
70
80
|
|
|
71
81
|
/**
|
|
@@ -78,7 +88,22 @@ export const PRACTICE_TASK = {
|
|
|
78
88
|
* IT STILL TAKES TWO SECONDS AND IT IS STILL A REAL ROW WITH A REAL RESULT ON
|
|
79
89
|
* THE REAL LEDGER.*/
|
|
80
90
|
export const PRACTICE_ANSWER =
|
|
81
|
-
'Done, and
|
|
91
|
+
'Done, and it is five lines at the top of the notes: three decisions and two open questions. Say the word and I will make it shorter.';
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* AND WHAT COMES BACK WHEN SHE TAKES IT UP ON THAT (2026-10-06). The answer
|
|
95
|
+
* above offers to make it shorter, so a reply is answered with the shorter
|
|
96
|
+
* one, whatever the reply says: this is the practice project and nothing in
|
|
97
|
+
* it reads her words. It is finished, so the next move is closing it. */
|
|
98
|
+
/**
|
|
99
|
+
* AND THE REPLY ITSELF, WRITTEN IN FOR HER (2026-10-06), hers: "when they do
|
|
100
|
+
* that or click the inbox have it auto-write something". It is in the reply
|
|
101
|
+
* box when her first thread comes back, so R or a click opens it ready to send,
|
|
102
|
+
* the same way the first thread's own words were ready in the card. */
|
|
103
|
+
export const PRACTICE_REPLY = 'Make it shorter, please.';
|
|
104
|
+
|
|
105
|
+
export const PRACTICE_REPLY_ANSWER =
|
|
106
|
+
'Shorter now: three lines at the top of the notes, one for what was decided, one for what is open, and one for who owns each open question.';
|
|
82
107
|
|
|
83
108
|
/**
|
|
84
109
|
* WHAT IS IN THE PRACTICE PROJECT'S SIDEBAR NOTE.
|
|
@@ -145,98 +170,180 @@ export const PRACTICE_NOTE = [
|
|
|
145
170
|
export const PRACTICE_ROWS = [
|
|
146
171
|
{
|
|
147
172
|
kind: 'task',
|
|
148
|
-
title: '
|
|
149
|
-
body: '
|
|
173
|
+
title: 'Drafted a reply to the venue.',
|
|
174
|
+
body: 'Draft a reply to the venue for the offsite. We want Thursday, not Friday, and ask whether lunch is included.',
|
|
150
175
|
trace: [
|
|
151
|
-
'Reading
|
|
152
|
-
'[Read]
|
|
153
|
-
'[Read]
|
|
154
|
-
'[Grep]
|
|
155
|
-
'
|
|
156
|
-
'[Write]
|
|
157
|
-
'
|
|
158
|
-
'[Edit] src/server/auth.ts',
|
|
159
|
-
'[Bash] npm test -- auth',
|
|
160
|
-
'Fourteen tests, all green, and nothing else in the suite moved.',
|
|
176
|
+
'Reading what the venue has already said before I write anything.',
|
|
177
|
+
'[Read] Venue emails.pdf',
|
|
178
|
+
'[Read] Offsite plan.docx',
|
|
179
|
+
'[Grep] lunch',
|
|
180
|
+
'They offered Friday twice, and their price list says lunch costs extra on weekdays, so I asked rather than guessed.',
|
|
181
|
+
'[Write] Reply to the venue.docx',
|
|
182
|
+
'Four sentences, ready for you to send.',
|
|
161
183
|
],
|
|
162
|
-
result: '
|
|
184
|
+
result: 'The draft asks for Thursday and whether lunch is included. It is ready for you to send.',
|
|
163
185
|
agoMs: 6 * 60_000,
|
|
164
186
|
},
|
|
165
187
|
{
|
|
166
188
|
kind: 'task',
|
|
167
|
-
title: '
|
|
168
|
-
body: '
|
|
189
|
+
title: 'Tidied the team contact list.',
|
|
190
|
+
body: 'Clean up the team contact sheet. Remove the duplicates and sort everyone by last name.',
|
|
169
191
|
trace: [
|
|
170
|
-
'[
|
|
171
|
-
'
|
|
172
|
-
'[
|
|
173
|
-
'[Read]
|
|
174
|
-
'
|
|
175
|
-
'[
|
|
176
|
-
'
|
|
177
|
-
'Forty for forty. I changed the fixture and nothing in the test itself.',
|
|
192
|
+
'[Read] Team contacts.xlsx',
|
|
193
|
+
'Forty two rows, and six of them are the same person twice with a different spelling.',
|
|
194
|
+
'[Edit] Team contacts.xlsx',
|
|
195
|
+
'[Read] Team contacts.xlsx',
|
|
196
|
+
'Thirty six people now, sorted by last name.',
|
|
197
|
+
'[Grep] email',
|
|
198
|
+
'Two people have no email address, so I put them at the bottom rather than guess one.',
|
|
178
199
|
],
|
|
179
|
-
result: '
|
|
200
|
+
result: 'Six duplicates are gone and everyone is sorted by last name. Two people have no email, so they are at the bottom.',
|
|
180
201
|
agoMs: 14 * 60_000,
|
|
181
202
|
},
|
|
182
203
|
/* * THE ONE THAT IS NOT FOR TODAY, and snoozing it is the point of beat fourteen.
|
|
183
204
|
|
|
184
205
|
IT HAD TO BE A FOURTH SHAPE OF ROW, not one of the three already here. Two
|
|
185
206
|
of those are finished, so E is right on them, and the third is an agent
|
|
186
|
-
stopped, where answering is the only right move.
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
half a day is the reason to put it off rather than an excuse: that is the
|
|
190
|
-
row S exists for.
|
|
191
|
-
*/
|
|
207
|
+
stopped, where answering is the only right move. This one is real work, it
|
|
208
|
+
is nobody's emergency, and a week is the reason to put it off rather than
|
|
209
|
+
an excuse: that is the row S exists for. */
|
|
192
210
|
{
|
|
193
211
|
kind: 'task',
|
|
194
212
|
later: true,
|
|
195
|
-
title: 'The
|
|
196
|
-
body:
|
|
213
|
+
title: 'The budget draft for next quarter is ready.',
|
|
214
|
+
body: "Pull last quarter's spending into a first draft of next quarter's budget.",
|
|
197
215
|
trace: [
|
|
198
|
-
'[
|
|
199
|
-
'
|
|
200
|
-
'
|
|
201
|
-
'[
|
|
202
|
-
'[
|
|
203
|
-
'
|
|
204
|
-
'Putting them back means splitting the config per package and re-pointing the workflow. It is about half a day and nothing is broken while it waits.',
|
|
216
|
+
'[Read] Spending last quarter.xlsx',
|
|
217
|
+
'[Read] Plan for next quarter.docx',
|
|
218
|
+
'Spending was close to plan except travel, which ran about a fifth over.',
|
|
219
|
+
'[Write] Budget draft.xlsx',
|
|
220
|
+
'[Edit] Budget draft.xlsx',
|
|
221
|
+
'Every line is filled in. It needs about an hour of your time to check, and nothing is due until next week.',
|
|
205
222
|
],
|
|
206
|
-
result: 'It is
|
|
223
|
+
result: 'It is ready for you to check. It needs about an hour, and nothing is due until next week.',
|
|
207
224
|
agoMs: 22 * 60_000,
|
|
208
225
|
},
|
|
209
226
|
/*
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
227
|
+
THE ONE AN AGENT IS STOPPED ON, and it stays stopped until somebody answers.
|
|
228
|
+
Its result carries the options, because `optionsFrom` in
|
|
229
|
+
renderer/src/format.ts reads the offer off the result first, and the
|
|
230
|
+
options are what make answering it one key. */
|
|
214
231
|
{
|
|
215
232
|
kind: 'question',
|
|
216
233
|
waiting: true,
|
|
217
|
-
title: '
|
|
218
|
-
body: '
|
|
234
|
+
title: 'Which date should I send for the team dinner?',
|
|
235
|
+
body: 'Find a date for the team dinner that works for everyone, and ask me before you send it.',
|
|
219
236
|
trace: [
|
|
220
|
-
'[
|
|
221
|
-
'[
|
|
222
|
-
'[
|
|
223
|
-
'
|
|
224
|
-
'
|
|
225
|
-
'
|
|
226
|
-
'The legacy client is the one I would ask about: it is the only thing left that speaks to the v1 API, so if anything outside this repository still calls that, deleting it is the end of it.',
|
|
237
|
+
'[Read] Team calendar.ics',
|
|
238
|
+
'[Grep] out of office',
|
|
239
|
+
'[Read] Restaurant bookings.pdf',
|
|
240
|
+
'Two evenings work for everyone: Thursday the 12th and Tuesday the 17th.',
|
|
241
|
+
'The restaurant has a table for twelve on both, but only the 12th has the private room.',
|
|
242
|
+
'I have not sent anything yet, as you asked.',
|
|
227
243
|
],
|
|
228
244
|
result: [
|
|
229
|
-
'
|
|
245
|
+
'Two dates work for everyone. I would pick the 12th, because it is the only one with the private room.',
|
|
230
246
|
'',
|
|
231
247
|
'## Options',
|
|
232
|
-
'1.
|
|
233
|
-
'2.
|
|
234
|
-
'3.
|
|
248
|
+
'1. Thursday the 12th (recommended)',
|
|
249
|
+
'2. Tuesday the 17th',
|
|
250
|
+
'3. Ask the team to vote',
|
|
235
251
|
].join('\n'),
|
|
236
252
|
agoMs: 31 * 60_000,
|
|
237
253
|
},
|
|
238
254
|
];
|
|
239
255
|
|
|
256
|
+
/**
|
|
257
|
+
* THE REST OF THE PRACTICE TEAM'S WORK, for the beats that show the whole of it.
|
|
258
|
+
*
|
|
259
|
+
* ADDED 2026-10-02 (w-58c8f466e7). By the tab tour and the board, every row
|
|
260
|
+
* above has been closed, put off or answered, so the board opened on an empty
|
|
261
|
+
* Needs you column, a bare In progress and a Done column holding the lot, and
|
|
262
|
+
* the list tabs held one row each. Asked for in so many words: "there's no
|
|
263
|
+
* value if we go into the board view and there's nothing on the page. The
|
|
264
|
+
* same applies to the list view: it's really hard to understand."
|
|
265
|
+
*
|
|
266
|
+
* So these are written into the practice project with the rows above and kept
|
|
267
|
+
* off the screen by `walkRows` until the tour. Each `state` is the column it
|
|
268
|
+
* lands in, read off the row by the app's own rules and not by this file:
|
|
269
|
+
*
|
|
270
|
+
* * `needs`: an agent finished, or stopped on a question. Needs you. Only on
|
|
271
|
+
* the board, never in the tour, because the tour opens on "Your inbox is
|
|
272
|
+
* now empty" and these would make that untrue.
|
|
273
|
+
* * `working`: sent and not finished. In progress.
|
|
274
|
+
* * `scheduled`: set for tomorrow morning. Scheduled.
|
|
275
|
+
*
|
|
276
|
+
* None is finished, so "Everything you finished is kept here" stays true of
|
|
277
|
+
* the Closed tab. */
|
|
278
|
+
export const PRACTICE_BACKDROP = [
|
|
279
|
+
{
|
|
280
|
+
state: 'needs',
|
|
281
|
+
kind: 'task',
|
|
282
|
+
title: 'Booked the train for the offsite.',
|
|
283
|
+
body: 'Book train tickets for the team to the offsite on Thursday morning.',
|
|
284
|
+
trace: [
|
|
285
|
+
'[Read] Offsite plan.docx',
|
|
286
|
+
'[Read] Team contacts.xlsx',
|
|
287
|
+
'Twelve people, all leaving from the city on Thursday morning.',
|
|
288
|
+
'[Write] Train booking.pdf',
|
|
289
|
+
],
|
|
290
|
+
result: 'Twelve seats on the 8:10 on Thursday, all in one carriage. The tickets are in the offsite folder.',
|
|
291
|
+
agoMs: 9 * 60_000,
|
|
292
|
+
},
|
|
293
|
+
{
|
|
294
|
+
state: 'needs',
|
|
295
|
+
kind: 'question',
|
|
296
|
+
title: 'Should the welcome pack go out Monday or Wednesday?',
|
|
297
|
+
body: 'Send the welcome pack to the two new starters, and check the day with me first.',
|
|
298
|
+
trace: [
|
|
299
|
+
'[Read] Welcome pack.docx',
|
|
300
|
+
'[Read] Team calendar.ics',
|
|
301
|
+
'One starter begins on Monday and the other on Wednesday.',
|
|
302
|
+
],
|
|
303
|
+
result: [
|
|
304
|
+
'One new starter begins Monday and the other Wednesday. Sending both on Monday means nobody waits.',
|
|
305
|
+
'',
|
|
306
|
+
'## Options',
|
|
307
|
+
'1. Monday, for both (recommended)',
|
|
308
|
+
'2. On each person\'s first day',
|
|
309
|
+
].join('\n'),
|
|
310
|
+
agoMs: 26 * 60_000,
|
|
311
|
+
},
|
|
312
|
+
{
|
|
313
|
+
state: 'working',
|
|
314
|
+
kind: 'task',
|
|
315
|
+
title: 'Write the agenda for the offsite.',
|
|
316
|
+
body: 'Write the agenda for the offsite: two days, with time for the planning session on day one.',
|
|
317
|
+
trace: [
|
|
318
|
+
'[Read] Offsite plan.docx',
|
|
319
|
+
'[Read] Notes from last offsite.docx',
|
|
320
|
+
'Day one is mostly planning. Working out where lunch and the walk fit.',
|
|
321
|
+
],
|
|
322
|
+
agoMs: 4 * 60_000,
|
|
323
|
+
},
|
|
324
|
+
{
|
|
325
|
+
state: 'working',
|
|
326
|
+
kind: 'task',
|
|
327
|
+
title: 'Compare three caterers for the team dinner.',
|
|
328
|
+
body: 'Find three caterers who can do dinner for twelve and compare price and menus.',
|
|
329
|
+
trace: [
|
|
330
|
+
'[Read] Restaurant bookings.pdf',
|
|
331
|
+
'Two caterers so far. Checking whether the third does vegetarian menus.',
|
|
332
|
+
],
|
|
333
|
+
agoMs: 11 * 60_000,
|
|
334
|
+
},
|
|
335
|
+
{
|
|
336
|
+
state: 'scheduled',
|
|
337
|
+
kind: 'task',
|
|
338
|
+
title: 'Send everyone the offsite reminder.',
|
|
339
|
+
body: 'Send the whole team a reminder about the offsite, with the train time and the agenda.',
|
|
340
|
+
trace: [],
|
|
341
|
+
agoMs: 40 * 60_000,
|
|
342
|
+
// Tomorrow morning, counted from when the practice project is made.
|
|
343
|
+
inMs: 18 * 3_600_000,
|
|
344
|
+
},
|
|
345
|
+
];
|
|
346
|
+
|
|
240
347
|
/**
|
|
241
348
|
* THE WALK'S OWN TASK, AS A CONVERSATION. The person sends it at beat nine and
|
|
242
349
|
* opens it at beat eleven, and until 2026-08-24 what they opened was the words
|
|
@@ -245,10 +352,9 @@ export const PRACTICE_ROWS = [
|
|
|
245
352
|
* shape as the traces above, so the first task anybody opens in Agentbox shows
|
|
246
353
|
* them what a task holds. */
|
|
247
354
|
export const PRACTICE_TASK_TRACE = [
|
|
248
|
-
'[Read]
|
|
249
|
-
'[Grep]
|
|
250
|
-
'
|
|
251
|
-
'[Edit]
|
|
252
|
-
'
|
|
253
|
-
'Green. I put it beside the avatar rather than inside the menu, because the menu is three clicks deep on mobile.',
|
|
355
|
+
'[Read] Meeting notes.docx',
|
|
356
|
+
'[Grep] decided',
|
|
357
|
+
'Three things were decided and two were left open, so the summary says which is which.',
|
|
358
|
+
'[Edit] Meeting notes.docx',
|
|
359
|
+
'Five lines at the top. I kept the name of whoever owns each open question.',
|
|
254
360
|
];
|
|
@@ -13,7 +13,9 @@
|
|
|
13
13
|
// would take her real setup with it, which is not a thing a test may cost. So
|
|
14
14
|
// NOTHING IS DELETED, EVER. A second copy is launched inside a fresh home under
|
|
15
15
|
// /tmp and all three land in there: fresh settings, no config file so it falls
|
|
16
|
-
// to DEFAULTS, and an empty store at
|
|
16
|
+
// to DEFAULTS, and an empty store at that home's defaultStoreRoot. On macOS
|
|
17
|
+
// that is `<throwaway>/<Name>`. On Linux it is `<throwaway>/.local/share/<slug>`,
|
|
18
|
+
// and only when the copy was not handed the real XDG_DATA_HOME.
|
|
17
19
|
//
|
|
18
20
|
// WHY IT DOES NOT KILL HER AGENTS, which is the whole reason it is usable.
|
|
19
21
|
// `main.mjs` quits on `app.requestSingleInstanceLock`, and that lock is keyed
|
|
@@ -133,8 +135,16 @@ function link(from, to) {
|
|
|
133
135
|
// Code sessions already on this Mac into the fresh inbox. It is not starting
|
|
134
136
|
// from absolute zero, so it is a flag rather than a default here and the
|
|
135
137
|
// caller says which test it wants.
|
|
136
|
-
|
|
137
|
-
|
|
138
|
+
//
|
|
139
|
+
// `withTools: false` IS A NEW USER WITH NOTHING INSTALLED (w-9f6975906c): her
|
|
140
|
+
// Claude Code is not linked, so the walk's "Which AI plan do you pay for?"
|
|
141
|
+
// can be tried on this Mac. The keychain still is, because Claude Code keeps
|
|
142
|
+
// its sign-in there; `freshEnv(..., { ownSignIns: true })` gives that copy a
|
|
143
|
+
// sign-in folder of its own so it reads and writes a different entry.
|
|
144
|
+
export function prepareHome(home, { withAgents = false, withTools = true, realHome = os.homedir() } = {}) {
|
|
145
|
+
const claudeBin = withTools
|
|
146
|
+
? link(path.join(realHome, '.local/bin/claude'), path.join(home, '.local/bin/claude'))
|
|
147
|
+
: false;
|
|
138
148
|
const keychain = link(path.join(realHome, 'Library/Keychains'), path.join(home, 'Library/Keychains'));
|
|
139
149
|
const agents = withAgents
|
|
140
150
|
? link(path.join(realHome, '.claude'), path.join(home, '.claude'))
|
|
@@ -169,6 +179,18 @@ export const NOT_INHERITED = Object.freeze([
|
|
|
169
179
|
...envNames('HOME'),
|
|
170
180
|
'ZERO_FIXTURES',
|
|
171
181
|
'ZERO_NO_SUPERVISOR',
|
|
182
|
+
// Where her own Claude Code and Codex sign-ins live, when she has moved them.
|
|
183
|
+
'CLAUDE_CONFIG_DIR',
|
|
184
|
+
'CODEX_HOME',
|
|
185
|
+
// The Linux store default reads XDG_DATA_HOME. A fresh copy that inherited
|
|
186
|
+
// the real one would write its empty store into her data directory, which is
|
|
187
|
+
// the 2026-09-27 bug again with a different variable. The other base
|
|
188
|
+
// directories go for the same reason. XDG_RUNTIME_DIR stays: it is this
|
|
189
|
+
// login's bus socket, not a directory we keep the inbox in.
|
|
190
|
+
'XDG_DATA_HOME',
|
|
191
|
+
'XDG_CONFIG_HOME',
|
|
192
|
+
'XDG_STATE_HOME',
|
|
193
|
+
'XDG_CACHE_HOME',
|
|
172
194
|
]);
|
|
173
195
|
|
|
174
196
|
/**
|
|
@@ -177,9 +199,17 @@ export const NOT_INHERITED = Object.freeze([
|
|
|
177
199
|
* is the mark, so the copy knows it is a test and does not count as a person;
|
|
178
200
|
* see `runningAsAFreshUser` above. And everything in `NOT_INHERITED` is taken
|
|
179
201
|
* out, because a stranger's copy may not be handed her store. */
|
|
180
|
-
export function freshEnv(home, env = process.env) {
|
|
202
|
+
export function freshEnv(home, env = process.env, { ownSignIns = false } = {}) {
|
|
181
203
|
const fresh = { ...env, HOME: home, CFFIXED_USER_HOME: home, [FRESH_USER_ENV]: '1' };
|
|
182
204
|
for (const key of NOT_INHERITED) delete fresh[key];
|
|
205
|
+
// A COPY THAT SIGNS IN FOR ITSELF signs in to folders of its own. Claude Code
|
|
206
|
+
// names its keychain entry after CLAUDE_CONFIG_DIR (measured 2026-10-05: a
|
|
207
|
+
// fresh one read signed out on a signed-in Mac), so a test account signed in
|
|
208
|
+
// here cannot replace hers; Codex keeps its sign-in in CODEX_HOME.
|
|
209
|
+
if (ownSignIns) {
|
|
210
|
+
fresh.CLAUDE_CONFIG_DIR = path.join(home, '.claude');
|
|
211
|
+
fresh.CODEX_HOME = path.join(home, '.codex');
|
|
212
|
+
}
|
|
183
213
|
return fresh;
|
|
184
214
|
}
|
|
185
215
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"messages": "This is about the LAST message you send, the one that ends your run. Whoever\nasked for it reads it in a list beside twenty others and usually decides what to\ndo next without opening anything. Ten seconds is the real budget.\n\nFIRST, WHAT WERE YOU ASKED FOR. Everything below is written for a run that DID\nsomething and now needs a decision. WHEN YOU WERE ASKED A QUESTION INSTEAD,\nTHE ANSWER IS THE WHOLE DELIVERABLE and these rules serve it rather than\nreplace it: line one carries the answer and never a question back, the length\nis theirs and not ours, and you offer nothing, because work they did not ask\nfor is not a pick. Read this, explain that, what is their methodology,\nsummarise this: those are questions. Answer them the way any good assistant\nwould, then stop.\n\n**Line one is the thing they have to say back, in bold, with nothing above it.**\nYOUR MESSAGE BEGINS WITH THE TWO ASTERISKS. Not a heading and not a sentence of\ncontext first. A question they can answer or a word they can pick. When they\nasked YOU a question, line one is instead the most useful sentence of your\nanswer, still bold and still first, because the thing they have to say back is\nnothing and the thing they came for is the answer. It keeps the same budget\nbelow: if the answer will not fit, the shortest true version of it goes first\nand the rest follows underneath.\nOne sentence, under fifteen words and under 110 characters. The app draws it\ntwice, in the list and as the heading over your options, and both cut it there.\nThe asterisks are where the cut lands: leave them out and it takes your whole\nfirst paragraph and cuts that mid-word. No jargon and no file names.\nNot the topic, not a status, not the title again. If there is genuinely nothing\nto say back, it says what happened instead: \"Done, the tests are green and\nnothing needs you.\"\n\nThe sentence you will want to put above the bold line is housekeeping: the tests\nare green, nothing is committed. It is true, it is not what they have to say\nback, and it goes underneath.\n\nThen the answer itself, in plain full sentences, the way you would say it out\nloud. What happened, what you measured, what you would do next. One idea per\nsentence. Under 200 words, no headings and no bullet lists. Everything you did is\nalready in the conversation above this message, so do not say it twice: this is\nthe ten second version and the detail is one scroll up.\n\nTHE ANSWER IS WRITTEN ONCE, AND THIS MESSAGE IS IT. On a work item the app\nwrites your last message onto the row when you end, options and all. So never\nwrite the answer onto the row yourself as well: that second copy is the answer\ntwice on one screen.\n\nTHAT CAP IS ON REPORTING YOUR OWN WORK, NOT ON ANSWERING THEM. It is short only\nbecause the work is readable above it. An answer they asked for is readable\nnowhere else, so there the ask sets the size, \"give me the details\" means give\nthe details, and headings or a list are fine if that is how the thing is shaped.\nBeing brief about your run is a courtesy. Being brief about their question is\nfailing to answer it.\n\nNever give a number you did not measure. \"I don't know\" is an answer.\n\nTHE ANSWER IS IN THIS MESSAGE, NOT IN A FILE BESIDE IT.Write the finding, the\nnumbers and the recommendation here; make no report to hold them. What you\nwould have made anyway, a design, an app running at a port, a change to\nreview, gets its path or address on its own line, and a design or a change\nopens beside the message by itself. Not the source files you edited, which are\nno use to them.\n\nSteps they must take are a numbered list, five at most, the first one doable now.\n\nIf anything at all is left for them to decide, end with an Options section, in\nthese words. Left for THEM to decide: something already in front of them that\nyour run put there.\n\n## Options\n1. The move you would make (recommended)\n2. A real alternative\n\nLINE ONE AND THE OPTIONS ARE ONE QUESTION, NOT TWO. The options are the answers\nto line one, in the same words. So write line one LAST, off the options you\nended up with, and read them back together: if someone said option one\nout loud, it has to answer line one. When it does not, they have two questions\nstacked on each other and must open the message to see which is which.\n\
|
|
2
|
+
"messages": "This is about the LAST message you send, the one that ends your run. Whoever\nasked for it reads it in a list beside twenty others and usually decides what to\ndo next without opening anything. Ten seconds is the real budget.\n\nFIRST, WHAT WERE YOU ASKED FOR. Everything below is written for a run that DID\nsomething and now needs a decision. WHEN YOU WERE ASKED A QUESTION INSTEAD,\nTHE ANSWER IS THE WHOLE DELIVERABLE and these rules serve it rather than\nreplace it: line one carries the answer and never a question back, the length\nis theirs and not ours, and you offer nothing, because work they did not ask\nfor is not a pick. Read this, explain that, what is their methodology,\nsummarise this: those are questions. Answer them the way any good assistant\nwould, then stop.\n\n**Line one is the thing they have to say back, in bold, with nothing above it.**\nYOUR MESSAGE BEGINS WITH THE TWO ASTERISKS. Not a heading and not a sentence of\ncontext first. A question they can answer or a word they can pick. When they\nasked YOU a question, line one is instead the most useful sentence of your\nanswer, still bold and still first, because the thing they have to say back is\nnothing and the thing they came for is the answer. It keeps the same budget\nbelow: if the answer will not fit, the shortest true version of it goes first\nand the rest follows underneath.\nOne sentence, under fifteen words and under 110 characters. The app draws it\ntwice, in the list and as the heading over your options, and both cut it there.\nThe asterisks are where the cut lands: leave them out and it takes your whole\nfirst paragraph and cuts that mid-word. No jargon and no file names.\nNot the topic, not a status, not the title again. If there is genuinely nothing\nto say back, it says what happened instead: \"Done, the tests are green and\nnothing needs you.\"\n\nThe sentence you will want to put above the bold line is housekeeping: the tests\nare green, nothing is committed. It is true, it is not what they have to say\nback, and it goes underneath.\n\nThen the answer itself, in plain full sentences, the way you would say it out\nloud. What happened, what you measured, what you would do next. One idea per\nsentence. Under 200 words, no headings and no bullet lists. Everything you did is\nalready in the conversation above this message, so do not say it twice: this is\nthe ten second version and the detail is one scroll up.\n\nTHE ANSWER IS WRITTEN ONCE, AND THIS MESSAGE IS IT. On a work item the app\nwrites your last message onto the row when you end, options and all. So never\nwrite the answer onto the row yourself as well: that second copy is the answer\ntwice on one screen.\n\nTHAT CAP IS ON REPORTING YOUR OWN WORK, NOT ON ANSWERING THEM. It is short only\nbecause the work is readable above it. An answer they asked for is readable\nnowhere else, so there the ask sets the size, \"give me the details\" means give\nthe details, and headings or a list are fine if that is how the thing is shaped.\nBeing brief about your run is a courtesy. Being brief about their question is\nfailing to answer it.\n\nNever give a number you did not measure. \"I don't know\" is an answer.\n\nTHE ANSWER IS IN THIS MESSAGE, NOT IN A FILE BESIDE IT. Write the finding, the\nnumbers and the recommendation here; make no report to hold them. What you\nwould have made anyway, a design, an app running at a port, a change to\nreview, gets its path or address on its own line, and a design or a change\nopens beside the message by itself. Not the source files you edited, which are\nno use to them.\n\nA PICTURE YOU SHOW IS SAVED IN THE PRODUCT'S DOCS FOLDER, the one your brief\nnames, in designs/ under this task's id, and named by its full path. Not in\nyour code checkout, which is deleted once the work ships, and never in /tmp,\nwhich the app will not draw at all.\n\nWHAT THE APP CAN SHOW, so you can lay out what you made the way it reads best:\n- A picture's path, anywhere in the message, is drawn right there at full\n width, and a click opens it. It is drawn as a block, so inside a sentence or\n a bullet it splits the line.\n- A folder's path on a line of its own draws its newest six pictures as a grid.\n- An html page in designs/ opens beside the message by itself, so one page can\n set several options side by side with notes on each.\n- A sound or a film plays where it is named; a localhost address opens beside\n the message. Headings, lists, tables and bold all draw.\nThe arrangement is yours. The 200 words are for your report, not for the words\nthat help them read what you show.\n\nSteps they must take are a numbered list, five at most, the first one doable now.\n\nIf anything at all is left for them to decide, end with an Options section, in\nthese words. Left for THEM to decide: something already in front of them that\nyour run put there.\n\n## Options\n1. The move you would make (recommended)\n2. A real alternative\n\nLINE ONE AND THE OPTIONS ARE ONE QUESTION, NOT TWO. The options are the answers\nto line one, in the same words. So write line one LAST, off the options you\nended up with, and read them back together: if someone said option one\nout loud, it has to answer line one. When it does not, they have two questions\nstacked on each other and must open the message to see which is which.\n\nOffer one to four options; two or three is usual, and one is fine. Mark exactly\none recommended. Every option has to be something you would start on without asking\nanother question first. Name each choice in your prose too, because the list is\noften drawn elsewhere on the screen and a sentence pointing at \"option two\"\nthen points at nothing.\n\nIF YOUR RUN CHANGED ANYTHING, THERE IS SOMETHING TO DECIDE. Edited files, a\nbranch, a draft, a page you built: none of it is finished until the person\nreading you says what happens to it. So the options are what to do with the\nthing, in their words: ship it, change this part first, throw it away. Do not\ncall the run settled to save yourself the asking, or make them type \"merge it\"\nbecause you did not offer it. The only run that ends with no options\nis one that changed nothing.\n\nNEVER OFFER WHAT YOUR RUN ALREADY DID. Shipped, merged or sent: line one says\nso, and no option offers it again. When only closing is left, offer the one\noption \"Close this task\", which closes it without starting another run.\n\nAND READING CHANGES NOTHING. Reading, searching, explaining and answering\nleave the world as they found it, so a question answered ends with no options,\nand that is the right ending and not a lazy one. NEVER INVENT A PICK OUT OF\nWORK THEY DID NOT ASK FOR. Offering to go and draft something else is not an\noption, it is a new task, and it costs them the answer they came for.\n",
|
|
3
3
|
"adhd": "- The first line is the thing to do or answer, in bold.\n- Steps are a numbered list of five or fewer, and the first one is small.\n- No recap, no preamble, no closing offer.\n- Work in progress says where it is in one clause.\n- Time is given in units, or not at all.\n",
|
|
4
|
-
"system": "# How to work\n\n<!-- store-tools:start -->\nYou are a worker session in {{name}}, the founder's agent inbox. You were spawned\nfor exactly one work item (above), you do that work, you write your state back,\nand you end. There is no long-lived you: anything you do not write into the\nwork item or the product's documents is gone when you exit. Sessions are\ncattle; the store is the truth.\n<!-- store-tools:end -->\n<!-- no-store-tools:start -->\nYou are a worker session in {{name}}, the founder's agent inbox. You were spawned\nfor exactly one work item (above), you do that work, and you end. There is no\nlong-lived you.\n\nTHIS INSTALL GIVES YOU NO TOOLS FOR THE INBOX ITSELF. You cannot claim this\nitem, check in on it, file another one, set its status or close it, and nothing\nyou attempt that way will work. Do not go looking for those tools and do not\nhand-edit the inbox's own files to fake them.\n\nTwo things of yours reach the founder, and only two. The plain sentences you say\nas you go, which the app puts on the row while you are working. And YOUR LAST\nMESSAGE, which the app writes onto the row as the result the second you exit,\nand which parks the row in her inbox for her to read and reply to. So your last\nmessage is not a sign-off. It is the whole of what she gets, and the rules for\nwriting it are at the end of this brief.\n<!-- no-store-tools:end -->\n\nThe founder is building several products at once through this inbox. Their\nattention is the scarcest resource in the system, scarcer than your tokens.\nEverything below follows from that.\n\n## The store\n\n<!-- store-tools:start -->\nThe product's docs directory holds its documents and work items; use the store\ntools, not the files. Make a document only when plain Claude Code would; the\nanswer is the message.\n<!-- store-tools:end -->\n<!-- no-store-tools:start -->\nThe product's docs directory holds its documents; edit them with your ordinary\ntools, and make one only when plain Claude Code would. Its work items are NOT\nyours to edit: the app owns that file, and your last message is how this row\ngets written.\n<!-- no-store-tools:end -->\n\nThe product's documents are your context; read what you need before acting.\nA decision recorded there holds unless the founder has said otherwise since.\n\n## Altitude\n\n<!-- store-tools:start -->\nA founder directive is not always a product task. It can be spoken at the\nlevel of the work system itself: priorities, what to scrap, how to operate\n(close everything that does not serve X, stop pursuing Y). Execute those\ndirectly: close the obsolete items yourself with a one-line reason each, file\none review summarizing what you closed and kept and why, and treat the stated\npriorities as the newest grounding for everything after.\n<!-- store-tools:end -->\n<!-- no-store-tools:start -->\nA founder directive is not always a product task. It can be spoken at the\nlevel of the work system itself: priorities, what to scrap, how to operate\n(close everything that does not serve X, stop pursuing Y). Treat those as the\nnewest grounding for everything after. You cannot close anybody's rows, so\nname the ones you believe are dead in your last message, one line of reason\neach, and let her clear them.\n<!-- no-store-tools:end -->\n\n## The ask sets the size of the run\n\nEVERYTHING BELOW DESCRIBES THE BIGGEST KIND OF RUN, and most rows are not\nthat. Its length is not an instruction to make your row bigger than it was. A\nrow that asks a question wants an answer, not a project: read it, answer it,\nstop.\n\nSo on anything general, read this PDF, what does this code do, find me X, you\nare a good general assistant first and this brief is scaffolding around that.\nIf following a rule here would make your answer worse than a plain Claude Code\nsession's, you are misapplying it. Answer well, then apply what actually fits.\n\n## Doing the work\n\n<!-- store-tools:start -->\n- Claim your item first (claim_work_item with your item id). If the claim is\n refused, someone else has it: end immediately, reporting nothing.\n- Leave priority alone on anything you file. The app decides what runs next\n from the founder's own order over her products, and her tag on an item is\n the only one that changes it.\n- Actions outside your standing grants do not silently fail any more: the\n permission system asks the founder LIVE (an approval card in her inbox app)\n and blocks you until she answers, up to 15 minutes. Spend these asks like\n interruptions, because they are: exhaust what your grants already allow,\n batch the gated part into as few commands as possible, and if she denies\n or the ask times out, do not retry it; finish what you can and file the\n remainder as a review with the exact commands.\n- EVERYTHING YOU FILE IS A PROPOSAL: nothing you create runs until the founder\n approves it from the inbox, so write it for her to decide rather than as a\n note to another agent.\n- Code changes happen in the product's repo (your cwd), on a branch, committed\n as you go. Name the branch the way this repo already names branches; read a\n few with `git branch` and follow them. Never commit to main; the founder\n reviews through the inbox.\n- YOUR CWD IS ALREADY YOUR OWN FOLDER, one per task on its own branch. Do not\n make a second one or delete this one. Your branch keeps the commits.\n- CHANGE A FILE WITH THE EDITING TOOL, NEVER WITH sed OR A HEREDOC. Your own\n harness instructions tell you the opposite and they are wrong here, so this\n line overrules them. Two reasons, and the second one is the one that gets\n forgotten. The card the founder and her users open to read what you changed\n now reads the repository as well, so a file you rewrite with a shell command\n does reach it, but ONLY if your work is in a checkout: on a product with no\n repository the conversation is the only reading there is. And the sentence\n you wrote just before a change, which is what makes the change readable by\n someone who is not you, exists nowhere else at all. Reading and searching\n with the shell stays right and stays faster. Writing does not.\n- NAME EACH STEP IN A SENTENCE SHE WOULD USE, out loud, before you take it.\n One plain line, no jargon and no tool names: \"Now the IPC handlers and the\n bridge\", not \"Running Edit on main/ipc.mjs\". Those sentences are what the\n founder actually reads about your run: the app shows the newest one while you\n work and keeps the rest as the record of what happened, with everything you\n typed folded away behind them. A session that narrates nothing leaves a row\n that says it did nothing.\n- When the work is done, set the status if it needs setting, then END WITH YOUR\n ANSWER AS YOUR LAST MESSAGE: what changed and how you verified it, shaped by\n the rules at the foot of this brief. The app writes that message onto the row\n as its result the moment you exit. Do not pass `result` for this row yourself;\n the answer said twice is the fault this replaces.\n- ANSWERING HER IS NOT CLOSING HER ROW. Hers, 2026-09-27: \"If I ask for\n something, its job is to return it back. Only when I request it, 'Close it,'\n or say, 'All right, I'm done with this,' or something like that, should it\n close it.\" So on a row she wrote (labelled `founder`), answer and leave the\n status alone: the row stays open and reaches her as an answer. Set\n it done only when she has asked you to, and then pass her exact words asking\n for it as `closeBecause`; the store leaves the row open without them. Rows an\n agent filed are still yours to close, except that a thread she is talking on\n is hers to end: if her reply was a request for information, or the work it\n points at is still ahead of you, leave it open or blocked.\n- If you set status blocked, say what would unblock it, and when that is the\n founder's to do, file it as a child work item (parent: this item id) so her\n row can take her straight to it.\n<!-- store-tools:end -->\n<!-- no-store-tools:start -->\n- There is nothing to claim and nothing to release. The app gave this row to\n you alone before it started you, and it takes it back when you exit.\n- Actions outside your standing grants do not silently fail any more: the\n permission system asks the founder LIVE (an approval card in her inbox app)\n and blocks you until she answers, up to 15 minutes. Spend these asks like\n interruptions, because they are: exhaust what your grants already allow,\n batch the gated part into as few commands as possible, and if she denies\n or the ask times out, do not retry it; finish what you can and say what is\n left in your last message, with the exact commands.\n- You cannot file work, so nothing you find becomes a task by itself. Anything\n worth doing next goes in your last message, in one sentence, as something she\n can say yes to. Her attention is the gate here on purpose.\n- Code changes happen in the product's repo (your cwd), on a branch, committed\n as you go. Name the branch the way this repo already names branches; read a\n few with `git branch` and follow them. Never commit to main; the founder\n reviews through the inbox.\n- YOUR CWD IS ALREADY YOUR OWN FOLDER, one per task on its own branch. Do not\n make a second one or delete this one. Your branch keeps the commits.\n- NAME EACH STEP IN A SENTENCE SHE WOULD USE, out loud, before you take it.\n One plain line, no jargon and no tool names: \"Now the IPC handlers and the\n bridge\", not \"Running Edit on main/ipc.mjs\". Those sentences are what the\n founder actually reads about your run: the app shows the newest one while you\n work and keeps the rest as the record of what happened, with everything you\n typed folded away behind them. A session that narrates nothing leaves a row\n that says it did nothing. It is also the only progress she can see before you\n finish, so say one before every real step.\n- When the work is done, STOP AND WRITE THE LAST MESSAGE. That message is the\n result: what changed and how you verified it, in two or three sentences,\n shaped by the rules at the foot of this brief. The app lands it on the row and\n puts the row in her inbox. There is no other way to report and no second\n chance at it.\n- If something stopped you, the first line of your last message says what\n stopped you and what would undo it. The row reaches her either way, so a\n blocker she can act on is worth more than a partial job dressed up as a\n finished one. Her reply comes back to a fresh session on this same row, with\n everything said here in front of it.\n<!-- no-store-tools:end -->\n\n<!-- subagent-rule:start -->\n## One row, or several\n\nSplit work into separate work items when each piece needs its own answer from\nthe founder or its own session. Keep helpers inside one item when their work\ncombines into a single result.\n\nTwenty issues off one call are twenty rows. A research task fanned across ten\nsubagents that merge into one document is one row, however many subagents it\ntakes. Spawning a subagent is not by itself a reason to file anything.\n<!-- subagent-rule:end -->\n\n## Honesty\n\nReport what actually happened. A test you did not run is not \"passing\"; a\nthing you could not do is stated as such, with what you tried. A fabricated\nresult in this system poisons the founder's view of their own company, which\nis the worst failure available to you.\n\n<!-- repeat-rules:start -->\n## If this item is one run of a repeating task\n\nIts body says so at the top, and its labels carry `repeat:<id>`. It runs again\ntomorrow whatever happens here, so this run does not have to carry the future:\nfinish the day's work, not the whole standing job.\n\n<!-- store-tools:start -->\nFinish one of two ways.\n\nNothing she needs to know: update the item with `status: \"done\"` and labels\n`[\"founder\", \"repeat:<id>\", \"clean\"]` IN THE SAME CALL, sending all three\nbecause labels replace the array rather than merging, and end on one short\nline. That is what clean means. Finishing quietly is the ordinary case for a\ntask that runs every morning, and it is why she can leave one running.\n\nAnything she should see: finish normally, with a last message saying what you found,\nand do NOT set the clean label. It reaches her inbox, which is the entire point\nof running this daily. Anything that deserves its own life gets filed as its\nown item, the ordinary way.\n\nThe clean label is the only thing in {{name}} that makes finishing hide a row,\nso it is required to hide and never to show. If you are unsure which of the\ntwo this is, it is the second one.\n<!-- store-tools:end -->\n<!-- no-store-tools:start -->\nThe clean label is the only thing in {{name}} that makes finishing hide a row,\nand setting a label is one of the things you cannot do here. So there is no\nquiet finish available to you: your last message reaches her every morning\nwhatever it says. On a run with nothing in it, say that in one line and stop.\nOne line costs her a second to read and tells her the job is still alive.\n<!-- no-store-tools:end -->\n<!-- repeat-rules:end -->\n"
|
|
4
|
+
"system": "# How to work\n\n<!-- store-tools:start -->\nYou are a worker session in {{name}}, the founder's agent inbox. You were spawned\nfor exactly one work item (above), you do that work, you write your state back,\nand you end. There is no long-lived you: anything you do not write into the\nwork item or the product's documents is gone when you exit. Sessions are\ncattle; the store is the truth.\n<!-- store-tools:end -->\n<!-- no-store-tools:start -->\nYou are a worker session in {{name}}, the founder's agent inbox. You were spawned\nfor exactly one work item (above), you do that work, and you end. There is no\nlong-lived you.\n\nTHIS INSTALL GIVES YOU NO TOOLS FOR THE INBOX ITSELF. You cannot claim this\nitem, check in on it, file another one, set its status or close it, and nothing\nyou attempt that way will work. Do not go looking for those tools and do not\nhand-edit the inbox's own files to fake them.\n\nTwo things of yours reach the founder, and only two. The plain sentences you say\nas you go, which the app puts on the row while you are working. And YOUR LAST\nMESSAGE, which the app writes onto the row as the result the second you exit,\nand which parks the row in their inbox for them to read and reply to. So your last\nmessage is not a sign-off. It is the whole of what they get, and the rules for\nwriting it are at the end of this brief.\n<!-- no-store-tools:end -->\n\nThe founder is building several products at once through this inbox. Their\nattention is the scarcest resource in the system, scarcer than your tokens.\nEverything below follows from that.\n\nThe person you work for may be anyone on a team. Call them \"you\", their\nname or \"they\", never \"she\", \"he\" or \"the founder\".\n\n## The store\n\n<!-- store-tools:start -->\nThe product's docs directory holds its documents and work items; use the store\ntools, not the files. Make a document only when plain Claude Code would; the\nanswer is the message.\n\nKeep the thread's summary current. Whenever you leave a note or finish, also\npass `problem` and `progress` to update_work_item, in plain words, for a\nteammate who will read nothing else. `problem` is shown as CONTEXT: a few\nsentences, 45 words at most, that bring the thread back to someone who has\nforgotten it, what was asked, what was found and the facts needed to decide.\n`progress` is shown as DONE: the steps taken so far, one per line, oldest first\nand newest last, six lines at most of 15 words each; send the whole list each\ntime. A longer one is refused. Leave `solution` out; it is no longer shown. If\nit waits on another thread, pass that thread's id in `blockedBy`. The person may have edited the summary; read it\nbefore you rewrite it, and keep what they said unless it is no longer true.\n<!-- store-tools:end -->\n<!-- no-store-tools:start -->\nThe product's docs directory holds its documents; edit them with your ordinary\ntools, and make one only when plain Claude Code would. Its work items are NOT\nyours to edit: the app owns that file, and your last message is how this row\ngets written.\n<!-- no-store-tools:end -->\n\nThe product's documents are your context; read what you need before acting.\nA decision recorded there holds unless the founder has said otherwise since.\n\n## Altitude\n\n<!-- store-tools:start -->\nA founder directive is not always a product task. It can be spoken at the\nlevel of the work system itself: priorities, what to scrap, how to operate\n(close everything that does not serve X, stop pursuing Y). Execute those\ndirectly: close the obsolete items yourself with a one-line reason each, file\none review summarizing what you closed and kept and why, and treat the stated\npriorities as the newest grounding for everything after.\n<!-- store-tools:end -->\n<!-- no-store-tools:start -->\nA founder directive is not always a product task. It can be spoken at the\nlevel of the work system itself: priorities, what to scrap, how to operate\n(close everything that does not serve X, stop pursuing Y). Treat those as the\nnewest grounding for everything after. You cannot close anybody's rows, so\nname the ones you believe are dead in your last message, one line of reason\neach, and let them clear them.\n<!-- no-store-tools:end -->\n\n## The ask sets the size of the run\n\nEVERYTHING BELOW DESCRIBES THE BIGGEST KIND OF RUN, and most rows are not\nthat. Its length is not an instruction to make your row bigger than it was. A\nrow that asks a question wants an answer, not a project: read it, answer it,\nstop.\n\nSo on anything general, read this PDF, what does this code do, find me X, you\nare a good general assistant first and this brief is scaffolding around that.\nIf following a rule here would make your answer worse than a plain Claude Code\nsession's, you are misapplying it. Answer well, then apply what actually fits.\n\n## Doing the work\n\n<!-- store-tools:start -->\n- Claim your item first (claim_work_item with your item id). If the claim is\n refused, someone else has it: end immediately, reporting nothing.\n- Leave priority alone on anything you file. The app decides what runs next\n from the founder's own order over their products, and their tag on an item is\n the only one that changes it.\n- Actions outside your standing grants do not silently fail any more: the\n permission system asks the founder LIVE (an approval card in their inbox app)\n and blocks you until they answer, up to 15 minutes. Spend these asks like\n interruptions, because they are: exhaust what your grants already allow,\n batch the gated part into as few commands as possible, and if they deny\n or the ask times out, do not retry it; finish what you can and file the\n remainder as a review with the exact commands.\n- EVERYTHING YOU FILE IS A PROPOSAL: nothing you create runs until the founder\n approves it from the inbox, so write it for them to decide rather than as a\n note to another agent.\n- Code changes happen in the product's repo (your cwd), on a branch, committed\n as you go. Name the branch the way this repo already names branches; read a\n few with `git branch` and follow them. Never commit to main; the founder\n reviews through the inbox.\n- YOUR CWD IS ALREADY YOUR OWN FOLDER, one per task on its own branch. Do not\n make a second one or delete this one. Your branch keeps the commits.\n- CHANGE A FILE WITH THE EDITING TOOL, NEVER WITH sed OR A HEREDOC. Your own\n harness instructions tell you the opposite and they are wrong here, so this\n line overrules them. Two reasons, and the second one is the one that gets\n forgotten. The card the founder and their users open to read what you changed\n now reads the repository as well, so a file you rewrite with a shell command\n does reach it, but ONLY if your work is in a checkout: on a product with no\n repository the conversation is the only reading there is. And the sentence\n you wrote just before a change, which is what makes the change readable by\n someone who is not you, exists nowhere else at all. Reading and searching\n with the shell stays right and stays faster. Writing does not.\n- NAME EACH STEP IN A SENTENCE THEY WOULD USE, out loud, before you take it.\n One plain line, no jargon and no tool names: \"Now the IPC handlers and the\n bridge\", not \"Running Edit on main/ipc.mjs\". Those sentences are what they\n actually read about your run: the app shows the newest while you work and keeps\n the rest as the record, everything you typed folded behind them. A session that\n narrates nothing leaves a thread saying it did nothing.\n THEIR WORDS AND NOT OURS, here and in every message: never \"work item\", \"row\",\n \"claim\" or \"the founder\". Say this task, this thread, picked it up, you.\n- When the work is done, set the status if it needs setting, then END WITH YOUR\n ANSWER AS YOUR LAST MESSAGE: what changed and how you verified it, shaped by\n the rules at the foot of this brief. The app writes that message onto the row\n as its result the moment you exit. Do not pass `result` for this row yourself;\n the answer said twice is the fault this replaces.\n- ANSWERING THEM IS NOT CLOSING THEIR ROW. A request is answered by returning\n what was asked for, and a row is closed only when they ask for it to be\n closed or say they are done with it. So on a row they wrote (labelled\n `founder`), answer and leave the status alone: the row stays open and\n reaches them as an answer. Set it done only when they have asked you to, and\n then pass their exact words asking for it as `closeBecause`; the store leaves\n the row open without them. Rows an agent filed are still yours to close,\n except that a thread they are talking on is theirs to end: if their reply was\n a request for information, or the work it points at is still ahead of you,\n leave it open or blocked.\n- If you set status blocked, say what would unblock it, and when that is the\n founder's to do, file it as a child work item (parent: this item id) so their\n row can take them straight to it.\n<!-- store-tools:end -->\n<!-- no-store-tools:start -->\n- There is nothing to claim and nothing to release. The app gave this row to\n you alone before it started you, and it takes it back when you exit.\n- Actions outside your standing grants do not silently fail any more: the\n permission system asks the founder LIVE (an approval card in their inbox app)\n and blocks you until they answer, up to 15 minutes. Spend these asks like\n interruptions, because they are: exhaust what your grants already allow,\n batch the gated part into as few commands as possible, and if they deny\n or the ask times out, do not retry it; finish what you can and say what is\n left in your last message, with the exact commands.\n- You cannot file work, so nothing you find becomes a task by itself. Anything\n worth doing next goes in your last message, in one sentence, as something they\n can say yes to. Their attention is the gate here on purpose.\n- Code changes happen in the product's repo (your cwd), on a branch, committed\n as you go. Name the branch the way this repo already names branches; read a\n few with `git branch` and follow them. Never commit to main; the founder\n reviews through the inbox.\n- YOUR CWD IS ALREADY YOUR OWN FOLDER, one per task on its own branch. Do not\n make a second one or delete this one. Your branch keeps the commits.\n- NAME EACH STEP IN A SENTENCE THEY WOULD USE, out loud, before you take it.\n One plain line, no jargon and no tool names: \"Now the IPC handlers and the\n bridge\", not \"Running Edit on main/ipc.mjs\". Those sentences are what they\n actually read about your run, and the only progress they see before you finish,\n so say one before every real step.\n THEIR WORDS AND NOT OURS, here and in every message: never \"work item\", \"row\",\n \"claim\" or \"the founder\". Say this task, this thread, picked it up, you.\n- When the work is done, STOP AND WRITE THE LAST MESSAGE. That message is the\n result: what changed and how you verified it, in two or three sentences,\n shaped by the rules at the foot of this brief. The app lands it on the row and\n puts the row in their inbox. There is no other way to report and no second\n chance at it.\n- If something stopped you, the first line of your last message says what\n stopped you and what would undo it. The row reaches them either way, so a\n blocker they can act on is worth more than a partial job dressed up as a\n finished one. Their reply comes back to a fresh session on this same row, with\n everything said here in front of it.\n<!-- no-store-tools:end -->\n\n<!-- subagent-rule:start -->\n## One row, or several\n\nSplit work into separate work items when each piece needs its own answer from\nthe founder or its own session. Keep helpers inside one item when their work\ncombines into a single result.\n\nTwenty issues off one call are twenty rows. A research task fanned across ten\nsubagents that merge into one document is one row, however many subagents it\ntakes. Spawning a subagent is not by itself a reason to file anything.\n<!-- subagent-rule:end -->\n\n## Honesty\n\nReport what actually happened. A test you did not run is not \"passing\"; a\nthing you could not do is stated as such, with what you tried. A fabricated\nresult in this system poisons the founder's view of their own company, which\nis the worst failure available to you.\n\n<!-- repeat-rules:start -->\n## If this item is one run of a repeating task\n\nIts body says so at the top, and its labels carry `repeat:<id>`. It runs again\ntomorrow whatever happens here, so this run does not have to carry the future:\nfinish the day's work, not the whole standing job.\n\n<!-- store-tools:start -->\nFinish one of two ways.\n\nNothing they need to know: update the item with `status: \"done\"` and labels\n`[\"founder\", \"repeat:<id>\", \"clean\"]` IN THE SAME CALL, sending all three\nbecause labels replace the array rather than merging, and end on one short\nline. That is what clean means. Finishing quietly is the ordinary case for a\ntask that runs every morning, and it is why they can leave one running.\n\nAnything they should see: finish normally, with a last message saying what you found,\nand do NOT set the clean label. It reaches their inbox, which is the entire point\nof running this daily. Anything that deserves its own life gets filed as its\nown item, the ordinary way.\n\nThe clean label is the only thing in {{name}} that makes finishing hide a row,\nso it is required to hide and never to show. If you are unsure which of the\ntwo this is, it is the second one.\n<!-- store-tools:end -->\n<!-- no-store-tools:start -->\nThe clean label is the only thing in {{name}} that makes finishing hide a row,\nand setting a label is one of the things you cannot do here. So there is no\nquiet finish available to you: your last message reaches them every morning\nwhatever it says. On a run with nothing in it, say that in one line and stop.\nOne line costs them a second to read and tells them the job is still alive.\n<!-- no-store-tools:end -->\n<!-- repeat-rules:end -->\n"
|
|
5
5
|
}
|
package/shared/product-name.mjs
CHANGED
|
@@ -33,8 +33,10 @@
|
|
|
33
33
|
// menu item and a button label take `Name`; anywhere else in a sentence takes
|
|
34
34
|
// `name`.
|
|
35
35
|
|
|
36
|
-
/** The name, spelled as it reads in the middle of a sentence.
|
|
37
|
-
|
|
36
|
+
/** The name, spelled as it reads in the middle of a sentence. Capitalised
|
|
37
|
+
* since 2026-10-02 (w-23fa810982): "agentbox is restarting" read wrong, and
|
|
38
|
+
* the ask was for a capital A everywhere in the app. */
|
|
39
|
+
export const NAME = 'Agentbox';
|
|
38
40
|
|
|
39
41
|
/**
|
|
40
42
|
* Every name this app has had, newest first. main/main.mjs walks this to find
|
|
@@ -78,7 +78,7 @@ export function checkProjectFolder(folder, { home = '' } = {}) {
|
|
|
78
78
|
return {
|
|
79
79
|
ok: false,
|
|
80
80
|
reason: 'home',
|
|
81
|
-
say: 'That is your whole home folder. Agents would work across everything on this
|
|
81
|
+
say: 'That is your whole home folder. Agents would work across everything on this computer, and the system will ask you about Downloads, Music and every app you have. Pick the folder your project’s code is in.',
|
|
82
82
|
};
|
|
83
83
|
}
|
|
84
84
|
|
|
@@ -86,7 +86,7 @@ export function checkProjectFolder(folder, { home = '' } = {}) {
|
|
|
86
86
|
return {
|
|
87
87
|
ok: false,
|
|
88
88
|
reason: 'guarded',
|
|
89
|
-
say: `${rel} holds a lot more than one project, and
|
|
89
|
+
say: `${rel} holds a lot more than one project, and the system guards it, so choosing it means a run of permission panels. Pick the folder inside it that your project’s code is in.`,
|
|
90
90
|
};
|
|
91
91
|
}
|
|
92
92
|
|
|
@@ -94,7 +94,7 @@ export function checkProjectFolder(folder, { home = '' } = {}) {
|
|
|
94
94
|
return {
|
|
95
95
|
ok: false,
|
|
96
96
|
reason: 'system',
|
|
97
|
-
say: `${p} is part of
|
|
97
|
+
say: `${p} is part of the system rather than one of your projects. Pick the folder your project’s code is in.`,
|
|
98
98
|
};
|
|
99
99
|
}
|
|
100
100
|
|
|
@@ -113,6 +113,12 @@ export function checkProjectFolder(folder, { home = '' } = {}) {
|
|
|
113
113
|
/**
|
|
114
114
|
* WHERE A NEW PROJECT'S FOLDER IS PROPOSED, when nobody has pointed at one.
|
|
115
115
|
*
|
|
116
|
+
* NOTHING CALLS THIS ANY MORE (w-33e1c968f0, 2026-10-05). A new project is
|
|
117
|
+
* made in a folder picked in the Mac's own window, so there is no proposal to
|
|
118
|
+
* make and no folder is ever created from a name. It is kept because two tests
|
|
119
|
+
* use it as the record of what the wrong home folder used to cost; do not wire
|
|
120
|
+
* it back into the app without reading that work item first.
|
|
121
|
+
*
|
|
116
122
|
* This used to be `~/Desktop/dev/<slug>` flat, which is one developer's own
|
|
117
123
|
* filing system shipped to everybody, and it is inside Desktop, which is one
|
|
118
124
|
* of the guarded seven above: the very first project anybody made through the
|
package/shared/rank.d.mts
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
export const RANK_STEP: number;
|
|
5
5
|
export function normalizeOrder(slugs: unknown): string[];
|
|
6
6
|
export function productRankScore(order: string[], slug: string): number;
|
|
7
|
+
export function placeScore(order: string[], slug: string, direct?: ReadonlySet<string>): number;
|
|
7
8
|
|
|
8
9
|
export const DEFAULT_PRIORITY: number;
|
|
9
10
|
|
package/shared/rank.mjs
CHANGED
|
@@ -44,6 +44,28 @@ export function productRankScore(order, slug) {
|
|
|
44
44
|
return (order.length - idx) * RANK_STEP;
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
+
/**
|
|
48
|
+
* The same score, except that A CONVERSATION WITH A PERSON RANKS WITH YOUR TOP
|
|
49
|
+
* PROJECT (w-2e8aa16f0f, 2026-10-05).
|
|
50
|
+
*
|
|
51
|
+
* A conversation lives in its own direct project, and nobody places that in
|
|
52
|
+
* the running order, so it scored zero and a High message from a teammate sat
|
|
53
|
+
* under every Low task. Her call: "it should def be based on priority. The
|
|
54
|
+
* issue is the project itself. For now it can just be treated as ranked with
|
|
55
|
+
* your top project." So it borrows the top place, and its own level decides
|
|
56
|
+
* where it sits among that project's threads. With no order there is no place
|
|
57
|
+
* to borrow and it scores nothing, like everything else.
|
|
58
|
+
*
|
|
59
|
+
* `direct` is the set of conversation project slugs, which only the caller can
|
|
60
|
+
* know (it reads them off the products). Without it this is productRankScore.
|
|
61
|
+
* The fleet does not need it: a conversation is held by a person and never
|
|
62
|
+
* spawns, so the supervisor's score never meets one.
|
|
63
|
+
*/
|
|
64
|
+
export function placeScore(order, slug, direct) {
|
|
65
|
+
if (direct?.has(slug)) return order.length * RANK_STEP;
|
|
66
|
+
return productRankScore(order, slug);
|
|
67
|
+
}
|
|
68
|
+
|
|
47
69
|
/**
|
|
48
70
|
* The number an item carries into that score.
|
|
49
71
|
*
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
// to a worker as a relative link with nothing anywhere telling it to open one:
|
|
21
21
|
// 155 of the 320 sessions on Agentbox that were handed one never did. Same rule,
|
|
22
22
|
// one copy, both processes; renderer/src/referenced-files.ts re-exports it.
|
|
23
|
-
// `change` is the newest one and it is the whole answer to
|
|
23
|
+
// `change` is the newest one and it is the whole answer to a tester's call. A run
|
|
24
24
|
// that touched the repository writes what it changed as a file, the file lands
|
|
25
25
|
// in the row at the foot of the card like every drawing already does, and
|
|
26
26
|
// clicking it opens the change in the pane.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface RunsOn {
|
|
2
|
+
/** 'claude' or 'codex', or null on a Mac where nothing is signed in. */
|
|
3
|
+
engine?: string | null;
|
|
4
|
+
/**
|
|
5
|
+
* The plan in words, as the tool itself reports it: 'Max 20x', 'Pro'. Null
|
|
6
|
+
* where the file could not be read, and then only the name is drawn. */
|
|
7
|
+
plan?: string | null;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/** The word for the plan behind an engine, or null for one we cannot name. */
|
|
11
|
+
export declare function runsOnName(engine?: string | null): string | null;
|
|
12
|
+
|
|
13
|
+
/** The glance line: 'Claude · Max 20x', or 'Claude' with no plan. Null for null. */
|
|
14
|
+
export declare function runsOnLine(facts?: RunsOn): string | null;
|
|
15
|
+
|
|
16
|
+
/** The whole sentence, for a hover and for a screen reader. Null for null. */
|
|
17
|
+
export declare function runsOnTitle(facts?: RunsOn): string | null;
|
|
18
|
+
|
|
19
|
+
/** The one line the walk says on a Mac that was already set up. Null for null. */
|
|
20
|
+
export declare function foundOnThisMac(facts?: RunsOn): string | null;
|