@bongos/core 1.20.2 → 1.20.3

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.
@@ -5,7 +5,7 @@
5
5
  "adr": "0341 D3",
6
6
  "reread": "node scripts/gds/page-reader.js --stale",
7
7
  "how": ["Generated by node scripts/gds/page-reader.js (BV2.TW04, task 1004315; ADR 0341 D3). Do not hand-edit.","One entry per page of docs/page-inventory.json. Lines are in page order: the default state first, and a line only another state shows sits where that state shows it, with its state named.","placement: placed = a docs/copy-registry.json row renders it (file, line, string_id); shared = shell text every page of the surface carries (top bar, sidebar, footer), with its row when the registry has one; unplaced = the registry cannot place it (a rewrite becomes an engineer task, ADR 0341 D4).","text keeps {…} where the registry row has a hole, or where a value the page read from its API was filled in. A string that is only such data is counted under omitted.data, not listed.","reading_hash is over the non-shared lines (key, section, text); files_hash is over the page's inventory files. --check compares files_hash only and never opens a browser.","Rendered through the hall-preview harness (hall) and the ui-design kit stub (landing, status), at 1280x800 with the clock pinned, so a reading is the fixture world's page."],
8
- "counts": {"pages":39,"lines":3739,"placed":1237,"shared":254,"unplaced":2248,"omitted_data":1941},
8
+ "counts": {"pages":39,"lines":3779,"placed":1270,"shared":254,"unplaced":2255,"omitted_data":1948},
9
9
  "pages": [
10
10
  {
11
11
  "id": "builders:atlas",
@@ -2452,11 +2452,11 @@
2452
2452
  "id": "builders:settings",
2453
2453
  "surface": "builders",
2454
2454
  "title": "Settings",
2455
- "states_read": ["account","access","preferences","sound","update"],
2456
- "files_hash": "0ab819571fc478af",
2457
- "reading_hash": "c06b8fe2ca8fad7b",
2458
- "counts": {"lines":117,"placed":77,"shared":5,"unplaced":35},
2459
- "omitted": {"data":79},
2455
+ "states_read": ["account","access","preferences","skills-walkthrough","sound","update"],
2456
+ "files_hash": "a237c2bc0d4338e7",
2457
+ "reading_hash": "3561d6024edc1678",
2458
+ "counts": {"lines":157,"placed":110,"shared":5,"unplaced":42},
2459
+ "omitted": {"data":86},
2460
2460
  "notes": [],
2461
2461
  "lines": [
2462
2462
  {"key":"L0001","section":"skip link","text":"Skip to content","placement":"shared","file":"modules/hall-ui/public/shell.js","line":767,"string_id":"87cee78ca134"},
@@ -2487,7 +2487,7 @@
2487
2487
  {"key":"L0026","section":"footer","text":"Sign out","placement":"shared","file":"modules/hall-ui/public/shell.js","line":464,"string_id":"1883ad7f07fc","state":"update","occurrences":5},
2488
2488
  {"key":"L0027","section":"Skill voices","text":"Skill voices","placement":"placed","file":"modules/hall-ui/public/settings.html","line":310,"string_id":"ecc12c1dd4de","state":"sound"},
2489
2489
  {"key":"L0028","section":"Skill voices","text":"Each slash-command can run on a different model. The system has a default for every skill; choose another to override it, or leave it on Default.","placement":"placed","file":"modules/hall-ui/public/settings.html","line":311,"string_id":"7f1b1c32d360","state":"sound"},
2490
- {"key":"L0029","section":"Skill voices","text":"Skill","placement":"unplaced","state":"sound"},
2490
+ {"key":"L0029","section":"Skill voices","text":"Skill","placement":"placed","file":"modules/hall-ui/public/settings-specialities.js","line":128,"string_id":"4b0ca7d7171f","state":"sound"},
2491
2491
  {"key":"L0030","section":"Skill voices","text":"Default","placement":"unplaced","state":"sound"},
2492
2492
  {"key":"L0031","section":"Skill voices","text":"Your choice","placement":"placed","file":"modules/hall-ui/public/settings.html","line":319,"string_id":"f96bc227dba0","state":"sound"},
2493
2493
  {"key":"L0032","section":"Skill voices","text":"no LLM","placement":"unplaced","state":"sound","occurrences":22},
@@ -2511,71 +2511,111 @@
2511
2511
  {"key":"L0050","section":"How Claude talks to you","text":"How Claude talks to you","placement":"placed","file":"modules/hall-ui/public/settings.html","line":193,"string_id":"0469a83cf1e8","state":"preferences"},
2512
2512
  {"key":"L0051","section":"How Claude talks to you","text":"How replies are pitched for you — the vocabulary assumed, how much hand-holding local tooling gets, how long an answer runs, and how much of the work behind it is narrated. These reach every session you start. The defaults assume no software-engineering background; change any of them and the rest stay as they are.","placement":"placed","file":"modules/hall-ui/public/settings.html","line":194,"string_id":"63dbe9873b4e","state":"preferences"},
2513
2513
  {"key":"L0052","section":"How Claude talks to you","text":"{…} file{…}","placement":"placed","file":"modules/hall-ui/public/gate.js","line":151,"string_id":"3efa67dc6e07","state":"preferences"},
2514
- {"key":"L0053","section":"Wandering","text":"Wandering","placement":"unplaced","state":"preferences"},
2515
- {"key":"L0054","section":"Wandering","text":"How readily Claude opens a","placement":"placed","file":"modules/hall-ui/public/settings.html","line":275,"string_id":"0bae5deb899d","state":"preferences"},
2516
- {"key":"L0055","section":"Wandering","text":"new thread","placement":"placed","file":"modules/hall-ui/public/settings.html","line":276,"string_id":"86f235ddfe01","state":"preferences"},
2517
- {"key":"L0056","section":"Wandering","text":"of work — a tangent, an investigation, an unprompted suggestion — instead of staying on your claimed task. It never limits the work on the task itself. Your rank sets the starting point; newcomers stay locked low.","placement":"placed","file":"modules/hall-ui/public/settings.html","line":276,"string_id":"99f88f2af2ee","state":"preferences"},
2518
- {"key":"L0057","section":"Wandering","text":"{…} file{…}","placement":"placed","file":"modules/hall-ui/public/gate.js","line":151,"string_id":"3efa67dc6e07","state":"preferences"},
2519
- {"key":"L0058","section":"Wandering","text":"default for your rank","placement":"placed","file":"modules/hall-ui/public/settings.js","line":420,"string_id":"4a287afb0892","state":"preferences"},
2520
- {"key":"L0059","section":"Wandering","text":"{…} and {…}","placement":"placed","file":"modules/hall-ui/public/profile-nudge.js","line":77,"string_id":"56b00d773232","state":"preferences"},
2521
- {"key":"L0060","section":"Wandering","text":"Now: {…}. Your rank allows up to {…}.","placement":"unplaced","state":"preferences"},
2522
- {"key":"L0061","section":"Rendering","text":"Rendering","placement":"unplaced","state":"preferences"},
2523
- {"key":"L0062","section":"Rendering","text":"How much your session cards — what","placement":"placed","file":"modules/hall-ui/public/settings.html","line":294,"string_id":"160adde1e398","state":"preferences"},
2524
- {"key":"L0063","section":"Rendering","text":", claiming, and shipping show — spend on explaining themselves. Richer cards say more and cost more tokens; leaner ones carry the same facts for less. By default this follows how Claude talks to you, so you can set it once in","placement":"placed","file":"modules/hall-ui/public/settings.html","line":295,"string_id":"1f8aceffb15e","state":"preferences"},
2525
- {"key":"L0064","section":"Rendering","text":"How Claude talks to you","placement":"placed","file":"modules/hall-ui/public/settings.html","line":193,"string_id":"0469a83cf1e8","state":"preferences"},
2526
- {"key":"L0065","section":"Rendering","text":"and leave this alone.","placement":"placed","file":"modules/hall-ui/public/settings.html","line":299,"string_id":"2177da93be9b","state":"preferences"},
2527
- {"key":"L0066","section":"Rendering","text":"Session card richness","placement":"placed","file":"modules/hall-ui/public/settings-render.js","line":83,"string_id":"64a1f055129e","state":"preferences"},
2528
- {"key":"L0067","section":"Rendering","text":"How much the claim and ship cards show. Richer cards explain more and cost more tokens; the confirmation line is always there whichever you pick.","placement":"placed","file":"modules/hall-ui/public/settings-render.js","line":84,"string_id":"d76a5fcbde7c","state":"preferences"},
2529
- {"key":"L0068","section":"Rendering","text":"Match my interaction profile","placement":"unplaced","state":"preferences"},
2530
- {"key":"L0069","section":"Rendering","text":"default ({…})","placement":"placed","file":"modules/hall-ui/public/settings-render.js","line":64,"string_id":"4adbb8da9999","state":"preferences"},
2531
- {"key":"L0070","section":"Rendering","text":"{…} Change that profile and this follows it.","placement":"placed","file":"modules/hall-ui/public/settings-render.js","line":65,"string_id":"de5b58a187c6","state":"preferences"},
2532
- {"key":"L0071","section":"Rendering","text":"{…} and {…}","placement":"placed","file":"modules/hall-ui/public/profile-nudge.js","line":77,"string_id":"56b00d773232","state":"preferences"},
2533
- {"key":"L0072","section":"Rendering","text":"Saves the moment you choose; applies from your next session.","placement":"placed","file":"modules/hall-ui/public/settings.html","line":303,"string_id":"72f24fcbe9e0","state":"preferences"},
2534
- {"key":"L0073","section":"CLI access","text":"CLI access","placement":"placed","file":"modules/hall-ui/public/settings.html","line":133,"string_id":"a015a43bfc7f","state":"access"},
2535
- {"key":"L0074","section":"CLI access","text":"Mint a fresh CLI token using this browser session and paste it into your terminal — the quick way back in when a","placement":"placed","file":"modules/hall-ui/public/settings.html","line":134,"string_id":"64e91044df43","state":"access"},
2536
- {"key":"L0075","section":"CLI access","text":"/builder-*","placement":"unplaced","state":"access"},
2537
- {"key":"L0076","section":"CLI access","text":"command says your session expired.","placement":"placed","file":"modules/hall-ui/public/settings.html","line":136,"string_id":"508ff7083048","state":"access"},
2538
- {"key":"L0077","section":"CLI access","text":"Re-issue CLI token","placement":"placed","file":"modules/hall-ui/public/settings.html","line":140,"string_id":"e60039795803","state":"access"},
2539
- {"key":"L0078","section":"CLI access","text":"paste it into your terminal — bypasses Device Flow.","placement":"placed","file":"modules/hall-ui/public/settings.html","line":141,"string_id":"25d2c940e672","state":"access"},
2540
- {"key":"L0079","section":"CLI access","text":"Tokens refresh on use; re-issuing never signs you out anywhere else.","placement":"placed","file":"modules/hall-ui/public/settings.html","line":144,"string_id":"7dfdc26f9f79","state":"access"},
2541
- {"key":"L0080","section":"Active sessions","text":"Active sessions","placement":"placed","file":"modules/hall-ui/public/settings.html","line":151,"string_id":"524188fe0078","state":"access"},
2542
- {"key":"L0081","section":"Active sessions","text":"Every place you are currently signed in — this browser, your terminal, any other machine. A session refreshes for another 24 hours each time it is used, so one you have forgotten about can stay alive indefinitely. If a token has leaked, end it here.","placement":"placed","file":"modules/hall-ui/public/settings.html","line":152,"string_id":"c188854da766","state":"access"},
2543
- {"key":"L0082","section":"Active sessions","text":"Browser","placement":"unplaced","state":"access"},
2544
- {"key":"L0083","section":"Active sessions","text":"this session","placement":"placed","file":"modules/hall-ui/public/settings-sessions.js","line":44,"string_id":"632527db5bca","state":"access"},
2545
- {"key":"L0084","section":"Active sessions","text":"last used {…} · signed in {…}","placement":"placed","file":"modules/hall-ui/public/settings-sessions.js","line":46,"string_id":"9018bf6e99eb","state":"access","occurrences":3},
2546
- {"key":"L0085","section":"Active sessions","text":"End session","placement":"placed","file":"modules/hall-ui/public/settings-sessions.js","line":46,"string_id":"8d2b4f119ee3","state":"access","occurrences":3},
2547
- {"key":"L0086","section":"Active sessions","text":"Terminal","placement":"unplaced","state":"access"},
2548
- {"key":"L0087","section":"Active sessions","text":"Session","placement":"unplaced","state":"access"},
2549
- {"key":"L0088","section":"Active sessions","text":"Sign out everywhere","placement":"placed","file":"modules/hall-ui/public/settings.html","line":160,"string_id":"8ad669ab2565","state":"access"},
2550
- {"key":"L0089","section":"Active sessions","text":"ends every session including this one — you will be asked to sign in again.","placement":"placed","file":"modules/hall-ui/public/settings.html","line":161,"string_id":"12a23cc46ace","state":"access"},
2551
- {"key":"L0090","section":"Active sessions","text":"Ending a session takes effect immediately; the token stops working on its very next request.","placement":"placed","file":"modules/hall-ui/public/settings.html","line":163,"string_id":"8e82771e5b63","state":"access"},
2552
- {"key":"L0091","section":"Image-generation key","text":"Image-generation key","placement":"placed","file":"modules/hall-ui/public/settings.html","line":173,"string_id":"783853467d52","state":"access","occurrences":2},
2553
- {"key":"L0092","section":"Image-generation key","text":"The art pipeline draws tiles and sprites with Google AI Studio (Gemini). Needed only if you generate art — your key, your bill, paid only for what you make.","placement":"placed","file":"modules/hall-ui/public/settings.html","line":174,"string_id":"600b90074021","state":"access"},
2554
- {"key":"L0093","section":"Image-generation key","text":"Your key","placement":"placed","file":"modules/hall-ui/public/settings.js","line":828,"string_id":"51fd6f1ecb2f","state":"access"},
2555
- {"key":"L0094","section":"Image-generation key","text":"Paste your Google AI Studio key","placement":"unplaced","attr":"placeholder","state":"access"},
2556
- {"key":"L0095","section":"Image-generation key","text":"Save key","placement":"placed","file":"modules/hall-ui/public/settings.js","line":832,"string_id":"0c79b504aebe","state":"access"},
2557
- {"key":"L0096","section":"Image-generation key","text":"Get a free key ↗","placement":"placed","file":"modules/hall-ui/public/settings.js","line":800,"string_id":"2ae2114b61db","state":"access"},
2558
- {"key":"L0097","section":"Image-generation key","text":"· Stored encrypted; never shown again after saving.","placement":"placed","file":"modules/hall-ui/public/settings.js","line":834,"string_id":"b3757ba3bb46","state":"access"},
2559
- {"key":"L0098","section":"Image-generation key","text":"Stored encrypted; never shown again after saving — only its last four digits.","placement":"placed","file":"modules/hall-ui/public/settings.html","line":182,"string_id":"6c6544f5c011","state":"access"},
2560
- {"key":"L0099","section":"Connections","text":"Connections","placement":"unplaced"},
2561
- {"key":"L0100","section":"Connections","text":"Link your Discord account and you're added to the {{worldName}} server with your rank role already set — no invite to share or leak.","placement":"placed","file":"modules/hall-ui/public/settings.html","line":64,"string_id":"64e85f1691f9"},
2562
- {"key":"L0101","section":"Connections","text":"Discord connected ✓","placement":"placed","file":"modules/hall-ui/public/settings.js","line":676,"string_id":"0f685daf1bd5"},
2563
- {"key":"L0102","section":"Connections","text":"You're in the {…} server with your rank role.","placement":"placed","file":"modules/hall-ui/public/settings.js","line":677,"string_id":"8e1915b19274"},
2564
- {"key":"L0103","section":"Connections","text":"Unlink","placement":"unplaced"},
2565
- {"key":"L0104","section":"Connections","text":"Linking opens Discord's consent screen; unlinking applies at once.","placement":"placed","file":"modules/hall-ui/public/settings.html","line":69,"string_id":"9a31cf5fe05b"},
2566
- {"key":"L0105","section":"Display name","text":"Display name","placement":"placed","file":"modules/hall-ui/public/settings.html","line":77,"string_id":"3e561393f4e9","occurrences":2},
2567
- {"key":"L0106","section":"Display name","text":"The name shown beside your work — in the roster, the leaderboard, and the work feed. Your sign-in and the credit for shipped work stay tied to your account, not this label.","placement":"placed","file":"modules/hall-ui/public/settings.html","line":78,"string_id":"82479c539fca"},
2568
- {"key":"L0107","section":"Display name","text":"Your display name","placement":"placed","file":"modules/hall-ui/public/settings.html","line":87,"string_id":"909b0b7c6ffa","attr":"placeholder"},
2569
- {"key":"L0108","section":"Display name","text":"Save","placement":"unplaced"},
2570
- {"key":"L0109","section":"Display name","text":"Saves when you press Save; shows everywhere at once.","placement":"placed","file":"modules/hall-ui/public/settings.html","line":91,"string_id":"e8e4e49fe8f4"},
2571
- {"key":"L0110","section":"Preferred roles","text":"Preferred roles","placement":"placed","file":"modules/hall-ui/public/settings.html","line":115,"string_id":"e883f2789cae"},
2572
- {"key":"L0111","section":"Preferred roles","text":"The kinds of work you prefer. Task suggestions lean toward your choices — pick one, several, or none.","placement":"placed","file":"modules/hall-ui/public/settings.html","line":116,"string_id":"9f45c63c9697"},
2573
- {"key":"L0112","section":"Preferred roles","text":"Artist","placement":"unplaced"},
2574
- {"key":"L0113","section":"Preferred roles","text":"Ideator","placement":"unplaced"},
2575
- {"key":"L0114","section":"Preferred roles","text":"UI","placement":"unplaced"},
2576
- {"key":"L0115","section":"Preferred roles","text":"Save","placement":"unplaced"},
2577
- {"key":"L0116","section":"Preferred roles","text":"Saves when you press Save; your next","placement":"placed","file":"modules/hall-ui/public/settings.html","line":125,"string_id":"42cbc20a6ec8"},
2578
- {"key":"L0117","section":"Preferred roles","text":"reflects it.","placement":"placed","file":"modules/hall-ui/public/settings.html","line":125,"string_id":"26da1df6fd4a"}
2514
+ {"key":"L0053","section":"Your specialities","text":"Your specialities","placement":"placed","file":"modules/hall-ui/public/settings.html","line":212,"string_id":"dd419ffd76f0","state":"preferences"},
2515
+ {"key":"L0054","section":"Your specialities","text":"A role says how you work. A speciality says what you work on — and how you, as someone who knows the subject, want to be engaged inside it. Whichever one you are using reaches every session where you hold a claim in that role. Train it by adding things you have written; it also picks things up on its own as you work.","placement":"placed","file":"modules/hall-ui/public/settings.html","line":213,"string_id":"244ea2a3564e","state":"preferences"},
2516
+ {"key":"L0055","section":"Your specialities","text":"Markets, incentives, and how to price them.","placement":"placed","file":"modules/hall-ui/public/settings.html","line":241,"string_id":"8bdec961e84a","state":"preferences"},
2517
+ {"key":"L0056","section":"Your specialities","text":"What this adds to your sessions — written by someone else","placement":"unplaced","state":"preferences"},
2518
+ {"key":"L0057","section":"Your specialities","text":"Argue from mechanism, not vibes. Always name the assumption a number rests on.","placement":"placed","file":"modules/hall-ui/public/settings.html","line":245,"string_id":"d9dd46194f35","state":"preferences"},
2519
+ {"key":"L0058","section":"Your specialities","text":"{…} and {…}","placement":"placed","file":"modules/hall-ui/public/profile-nudge.js","line":77,"string_id":"56b00d773232","state":"preferences","occurrences":2},
2520
+ {"key":"L0059","section":"Your specialities","text":"Trained on","placement":"placed","file":"modules/hall-ui/public/settings-specialities.js","line":220,"string_id":"becc35640e42","state":"preferences"},
2521
+ {"key":"L0060","section":"Your specialities","text":"document{…} you added · learned","placement":"placed","file":"modules/hall-ui/public/settings-specialities.js","line":220,"string_id":"a3fd52d9513b","state":"preferences"},
2522
+ {"key":"L0061","section":"Your specialities","text":"things from your sessions · shared with: Anyone on this instance · offers","placement":"unplaced","state":"preferences"},
2523
+ {"key":"L0062","section":"Your specialities","text":"skills","placement":"unplaced","state":"preferences"},
2524
+ {"key":"L0063","section":"Your specialities","text":"Use this","placement":"placed","file":"modules/hall-ui/public/settings-specialities.js","line":291,"string_id":"e7e2a99a2bea","state":"preferences"},
2525
+ {"key":"L0064","section":"Your specialities","text":"Skill {…} of {…} in {…}","placement":"placed","file":"modules/hall-ui/public/settings-specialities.js","line":128,"string_id":"4b0ca7d7171f","state":"skills-walkthrough"},
2526
+ {"key":"L0065","section":"Your specialities","text":"What it does","placement":"placed","file":"modules/hall-ui/public/settings-specialities.js","line":128,"string_id":"0efa2f18bb6c","state":"skills-walkthrough"},
2527
+ {"key":"L0066","section":"Your specialities","text":"{…} project{…}","placement":"placed","file":"modules/hall-ui/public/fleet.js","line":39,"string_id":"771bef3d31b5","state":"skills-walkthrough"},
2528
+ {"key":"L0067","section":"Your specialities","text":"When to reach for it","placement":"placed","file":"modules/hall-ui/public/settings-specialities.js","line":128,"string_id":"a6e102816e92","state":"skills-walkthrough"},
2529
+ {"key":"L0068","section":"Your specialities","text":"{…} You can also start it yourself by typing","placement":"unplaced","state":"skills-walkthrough"},
2530
+ {"key":"L0069","section":"Your specialities","text":"What it costs","placement":"placed","file":"modules/hall-ui/public/settings-specialities.js","line":128,"string_id":"65fd1339e2f2","state":"skills-walkthrough"},
2531
+ {"key":"L0070","section":"Your specialities","text":"These words come from the skill’s own description, which was written for Claude to recognise rather than for you to read — so a term may go unexplained.","placement":"placed","file":"modules/hall-ui/public/settings-specialities.js","line":126,"string_id":"775a73b066e3","state":"skills-walkthrough"},
2532
+ {"key":"L0071","section":"Your specialities","text":"Leave it off","placement":"placed","file":"modules/hall-ui/public/settings-specialities.js","line":136,"string_id":"6137d2679912","state":"skills-walkthrough"},
2533
+ {"key":"L0072","section":"Your specialities","text":"Turn it on","placement":"placed","file":"modules/hall-ui/public/settings-specialities.js","line":136,"string_id":"26ec8100bc6f","state":"skills-walkthrough"},
2534
+ {"key":"L0073","section":"Your specialities","text":"Finish later — everything stays off until you save","placement":"placed","file":"modules/hall-ui/public/settings-specialities.js","line":178,"string_id":"e8738f535783","state":"skills-walkthrough"},
2535
+ {"key":"L0074","section":"Create one","text":"Create one","placement":"placed","file":"modules/hall-ui/public/settings.html","line":224,"string_id":"20459b66303a","state":"preferences"},
2536
+ {"key":"L0075","section":"Create one","text":"Name","placement":"unplaced","state":"preferences"},
2537
+ {"key":"L0076","section":"Create one","text":"Role it sits under","placement":"placed","file":"modules/hall-ui/public/settings.html","line":230,"string_id":"12af2af5acf2","state":"preferences"},
2538
+ {"key":"L0077","section":"Create one","text":"Pick one…","placement":"placed","file":"modules/hall-ui/public/settings.html","line":232,"string_id":"45378ea261f6","state":"preferences"},
2539
+ {"key":"L0078","section":"Create one","text":"Ideator","placement":"unplaced","state":"preferences"},
2540
+ {"key":"L0079","section":"Create one","text":"Artist","placement":"unplaced","state":"preferences"},
2541
+ {"key":"L0080","section":"Create one","text":"UI design","placement":"placed","file":"modules/hall-ui/public/settings.html","line":236,"string_id":"6516cc82021a","state":"preferences"},
2542
+ {"key":"L0081","section":"Create one","text":"Summary","placement":"unplaced","state":"preferences"},
2543
+ {"key":"L0082","section":"Create one","text":"(optional)","placement":"unplaced","state":"preferences","occurrences":2},
2544
+ {"key":"L0083","section":"Create one","text":"Markets, incentives, and how to price them.","placement":"placed","file":"modules/hall-ui/public/settings.html","line":241,"string_id":"8bdec961e84a","attr":"placeholder","state":"preferences"},
2545
+ {"key":"L0084","section":"Create one","text":"How Claude should engage you in it","placement":"placed","file":"modules/hall-ui/public/settings.html","line":244,"string_id":"6dd3c797943b","state":"preferences"},
2546
+ {"key":"L0085","section":"Create one","text":"Argue from mechanism, not vibes. Always name the assumption a number rests on.","placement":"placed","file":"modules/hall-ui/public/settings.html","line":245,"string_id":"d9dd46194f35","attr":"placeholder","state":"preferences"},
2547
+ {"key":"L0086","section":"Create one","text":"Who can use it","placement":"placed","file":"modules/hall-ui/public/settings.html","line":248,"string_id":"b79ea4077bc5","state":"preferences"},
2548
+ {"key":"L0087","section":"Create one","text":"Only me","placement":"placed","file":"modules/hall-ui/public/settings.html","line":250,"string_id":"45b667751b95","state":"preferences"},
2549
+ {"key":"L0088","section":"Create one","text":"Anyone in the owning project","placement":"placed","file":"modules/hall-ui/public/settings.html","line":251,"string_id":"8832c7204180","state":"preferences"},
2550
+ {"key":"L0089","section":"Create one","text":"Anyone on this instance","placement":"placed","file":"modules/hall-ui/public/settings.html","line":252,"string_id":"7d2ab55d4112","state":"preferences"},
2551
+ {"key":"L0090","section":"Create one","text":"May be offered for sale later","placement":"placed","file":"modules/hall-ui/public/settings.html","line":257,"string_id":"6e73716aec6c","state":"preferences"},
2552
+ {"key":"L0091","section":"Create one","text":"Records your decision only — there is no marketplace yet, and nothing is listed anywhere.","placement":"placed","file":"modules/hall-ui/public/settings.html","line":259,"string_id":"b40c4a61070e","state":"preferences"},
2553
+ {"key":"L0092","section":"Create one","text":"Create speciality","placement":"placed","file":"modules/hall-ui/public/settings.html","line":263,"string_id":"af21de422c14","state":"preferences"},
2554
+ {"key":"L0093","section":"Wandering","text":"Wandering","placement":"unplaced","state":"preferences"},
2555
+ {"key":"L0094","section":"Wandering","text":"How readily Claude opens a","placement":"placed","file":"modules/hall-ui/public/settings.html","line":275,"string_id":"0bae5deb899d","state":"preferences"},
2556
+ {"key":"L0095","section":"Wandering","text":"new thread","placement":"placed","file":"modules/hall-ui/public/settings.html","line":276,"string_id":"86f235ddfe01","state":"preferences"},
2557
+ {"key":"L0096","section":"Wandering","text":"of work — a tangent, an investigation, an unprompted suggestion — instead of staying on your claimed task. It never limits the work on the task itself. Your rank sets the starting point; newcomers stay locked low.","placement":"placed","file":"modules/hall-ui/public/settings.html","line":276,"string_id":"99f88f2af2ee","state":"preferences"},
2558
+ {"key":"L0097","section":"Wandering","text":"{…} file{…}","placement":"placed","file":"modules/hall-ui/public/gate.js","line":151,"string_id":"3efa67dc6e07","state":"preferences"},
2559
+ {"key":"L0098","section":"Wandering","text":"default for your rank","placement":"placed","file":"modules/hall-ui/public/settings.js","line":420,"string_id":"4a287afb0892","state":"preferences"},
2560
+ {"key":"L0099","section":"Wandering","text":"{…} and {…}","placement":"placed","file":"modules/hall-ui/public/profile-nudge.js","line":77,"string_id":"56b00d773232","state":"preferences"},
2561
+ {"key":"L0100","section":"Wandering","text":"Now: {…}. Your rank allows up to {…}.","placement":"unplaced","state":"preferences"},
2562
+ {"key":"L0101","section":"Rendering","text":"Rendering","placement":"unplaced","state":"preferences"},
2563
+ {"key":"L0102","section":"Rendering","text":"How much your session cards — what","placement":"placed","file":"modules/hall-ui/public/settings.html","line":294,"string_id":"160adde1e398","state":"preferences"},
2564
+ {"key":"L0103","section":"Rendering","text":", claiming, and shipping show — spend on explaining themselves. Richer cards say more and cost more tokens; leaner ones carry the same facts for less. By default this follows how Claude talks to you, so you can set it once in","placement":"placed","file":"modules/hall-ui/public/settings.html","line":295,"string_id":"1f8aceffb15e","state":"preferences"},
2565
+ {"key":"L0104","section":"Rendering","text":"How Claude talks to you","placement":"placed","file":"modules/hall-ui/public/settings.html","line":193,"string_id":"0469a83cf1e8","state":"preferences"},
2566
+ {"key":"L0105","section":"Rendering","text":"and leave this alone.","placement":"placed","file":"modules/hall-ui/public/settings.html","line":299,"string_id":"2177da93be9b","state":"preferences"},
2567
+ {"key":"L0106","section":"Rendering","text":"Session card richness","placement":"placed","file":"modules/hall-ui/public/settings-render.js","line":83,"string_id":"64a1f055129e","state":"preferences"},
2568
+ {"key":"L0107","section":"Rendering","text":"How much the claim and ship cards show. Richer cards explain more and cost more tokens; the confirmation line is always there whichever you pick.","placement":"placed","file":"modules/hall-ui/public/settings-render.js","line":84,"string_id":"d76a5fcbde7c","state":"preferences"},
2569
+ {"key":"L0108","section":"Rendering","text":"Match my interaction profile","placement":"unplaced","state":"preferences"},
2570
+ {"key":"L0109","section":"Rendering","text":"default ({…})","placement":"placed","file":"modules/hall-ui/public/settings-render.js","line":64,"string_id":"4adbb8da9999","state":"preferences"},
2571
+ {"key":"L0110","section":"Rendering","text":"{…} Change that profile and this follows it.","placement":"placed","file":"modules/hall-ui/public/settings-render.js","line":65,"string_id":"de5b58a187c6","state":"preferences"},
2572
+ {"key":"L0111","section":"Rendering","text":"{…} and {…}","placement":"placed","file":"modules/hall-ui/public/profile-nudge.js","line":77,"string_id":"56b00d773232","state":"preferences"},
2573
+ {"key":"L0112","section":"Rendering","text":"Saves the moment you choose; applies from your next session.","placement":"placed","file":"modules/hall-ui/public/settings.html","line":303,"string_id":"72f24fcbe9e0","state":"preferences"},
2574
+ {"key":"L0113","section":"Rendering","text":"Using this speciality.","placement":"placed","file":"modules/hall-ui/public/settings-specialities.js","line":350,"string_id":"e1ecd543a2ca","state":"skills-walkthrough"},
2575
+ {"key":"L0114","section":"CLI access","text":"CLI access","placement":"placed","file":"modules/hall-ui/public/settings.html","line":133,"string_id":"a015a43bfc7f","state":"access"},
2576
+ {"key":"L0115","section":"CLI access","text":"Mint a fresh CLI token using this browser session and paste it into your terminal — the quick way back in when a","placement":"placed","file":"modules/hall-ui/public/settings.html","line":134,"string_id":"64e91044df43","state":"access"},
2577
+ {"key":"L0116","section":"CLI access","text":"command says your session expired.","placement":"placed","file":"modules/hall-ui/public/settings.html","line":136,"string_id":"508ff7083048","state":"access"},
2578
+ {"key":"L0117","section":"CLI access","text":"Re-issue CLI token","placement":"placed","file":"modules/hall-ui/public/settings.html","line":140,"string_id":"e60039795803","state":"access"},
2579
+ {"key":"L0118","section":"CLI access","text":"paste it into your terminal — bypasses Device Flow.","placement":"placed","file":"modules/hall-ui/public/settings.html","line":141,"string_id":"25d2c940e672","state":"access"},
2580
+ {"key":"L0119","section":"CLI access","text":"Tokens refresh on use; re-issuing never signs you out anywhere else.","placement":"placed","file":"modules/hall-ui/public/settings.html","line":144,"string_id":"7dfdc26f9f79","state":"access"},
2581
+ {"key":"L0120","section":"Active sessions","text":"Active sessions","placement":"placed","file":"modules/hall-ui/public/settings.html","line":151,"string_id":"524188fe0078","state":"access"},
2582
+ {"key":"L0121","section":"Active sessions","text":"Every place you are currently signed in — this browser, your terminal, any other machine. A session refreshes for another 24 hours each time it is used, so one you have forgotten about can stay alive indefinitely. If a token has leaked, end it here.","placement":"placed","file":"modules/hall-ui/public/settings.html","line":152,"string_id":"c188854da766","state":"access"},
2583
+ {"key":"L0122","section":"Active sessions","text":"Browser","placement":"unplaced","state":"access"},
2584
+ {"key":"L0123","section":"Active sessions","text":"this session","placement":"placed","file":"modules/hall-ui/public/settings-sessions.js","line":44,"string_id":"632527db5bca","state":"access"},
2585
+ {"key":"L0124","section":"Active sessions","text":"last used {…} · signed in {…}","placement":"placed","file":"modules/hall-ui/public/settings-sessions.js","line":46,"string_id":"9018bf6e99eb","state":"access","occurrences":3},
2586
+ {"key":"L0125","section":"Active sessions","text":"End session","placement":"placed","file":"modules/hall-ui/public/settings-sessions.js","line":46,"string_id":"8d2b4f119ee3","state":"access","occurrences":3},
2587
+ {"key":"L0126","section":"Active sessions","text":"Terminal","placement":"unplaced","state":"access"},
2588
+ {"key":"L0127","section":"Active sessions","text":"Session","placement":"unplaced","state":"access"},
2589
+ {"key":"L0128","section":"Active sessions","text":"Sign out everywhere","placement":"placed","file":"modules/hall-ui/public/settings.html","line":160,"string_id":"8ad669ab2565","state":"access"},
2590
+ {"key":"L0129","section":"Active sessions","text":"ends every session including this one — you will be asked to sign in again.","placement":"placed","file":"modules/hall-ui/public/settings.html","line":161,"string_id":"12a23cc46ace","state":"access"},
2591
+ {"key":"L0130","section":"Active sessions","text":"Ending a session takes effect immediately; the token stops working on its very next request.","placement":"placed","file":"modules/hall-ui/public/settings.html","line":163,"string_id":"8e82771e5b63","state":"access"},
2592
+ {"key":"L0131","section":"Image-generation key","text":"Image-generation key","placement":"placed","file":"modules/hall-ui/public/settings.html","line":173,"string_id":"783853467d52","state":"access","occurrences":2},
2593
+ {"key":"L0132","section":"Image-generation key","text":"The art pipeline draws tiles and sprites with Google AI Studio (Gemini). Needed only if you generate art — your key, your bill, paid only for what you make.","placement":"placed","file":"modules/hall-ui/public/settings.html","line":174,"string_id":"600b90074021","state":"access"},
2594
+ {"key":"L0133","section":"Image-generation key","text":"Your key","placement":"placed","file":"modules/hall-ui/public/settings.js","line":828,"string_id":"51fd6f1ecb2f","state":"access"},
2595
+ {"key":"L0134","section":"Image-generation key","text":"Paste your Google AI Studio key","placement":"unplaced","attr":"placeholder","state":"access"},
2596
+ {"key":"L0135","section":"Image-generation key","text":"Save key","placement":"placed","file":"modules/hall-ui/public/settings.js","line":832,"string_id":"0c79b504aebe","state":"access"},
2597
+ {"key":"L0136","section":"Image-generation key","text":"Get a free key ↗","placement":"placed","file":"modules/hall-ui/public/settings.js","line":800,"string_id":"2ae2114b61db","state":"access"},
2598
+ {"key":"L0137","section":"Image-generation key","text":"· Stored encrypted; never shown again after saving.","placement":"placed","file":"modules/hall-ui/public/settings.js","line":834,"string_id":"b3757ba3bb46","state":"access"},
2599
+ {"key":"L0138","section":"Image-generation key","text":"Stored encrypted; never shown again after saving — only its last four digits.","placement":"placed","file":"modules/hall-ui/public/settings.html","line":182,"string_id":"6c6544f5c011","state":"access"},
2600
+ {"key":"L0139","section":"Connections","text":"Connections","placement":"unplaced"},
2601
+ {"key":"L0140","section":"Connections","text":"Link your Discord account and you're added to the {{worldName}} server with your rank role already set — no invite to share or leak.","placement":"placed","file":"modules/hall-ui/public/settings.html","line":64,"string_id":"64e85f1691f9"},
2602
+ {"key":"L0141","section":"Connections","text":"Discord connected ✓","placement":"placed","file":"modules/hall-ui/public/settings.js","line":676,"string_id":"0f685daf1bd5"},
2603
+ {"key":"L0142","section":"Connections","text":"You're in the {…} server with your rank role.","placement":"placed","file":"modules/hall-ui/public/settings.js","line":677,"string_id":"8e1915b19274"},
2604
+ {"key":"L0143","section":"Connections","text":"Unlink","placement":"unplaced"},
2605
+ {"key":"L0144","section":"Connections","text":"Linking opens Discord's consent screen; unlinking applies at once.","placement":"placed","file":"modules/hall-ui/public/settings.html","line":69,"string_id":"9a31cf5fe05b"},
2606
+ {"key":"L0145","section":"Display name","text":"Display name","placement":"placed","file":"modules/hall-ui/public/settings.html","line":77,"string_id":"3e561393f4e9","occurrences":2},
2607
+ {"key":"L0146","section":"Display name","text":"The name shown beside your work — in the roster, the leaderboard, and the work feed. Your sign-in and the credit for shipped work stay tied to your account, not this label.","placement":"placed","file":"modules/hall-ui/public/settings.html","line":78,"string_id":"82479c539fca"},
2608
+ {"key":"L0147","section":"Display name","text":"Your display name","placement":"placed","file":"modules/hall-ui/public/settings.html","line":87,"string_id":"909b0b7c6ffa","attr":"placeholder"},
2609
+ {"key":"L0148","section":"Display name","text":"Save","placement":"unplaced"},
2610
+ {"key":"L0149","section":"Display name","text":"Saves when you press Save; shows everywhere at once.","placement":"placed","file":"modules/hall-ui/public/settings.html","line":91,"string_id":"e8e4e49fe8f4"},
2611
+ {"key":"L0150","section":"Preferred roles","text":"Preferred roles","placement":"placed","file":"modules/hall-ui/public/settings.html","line":115,"string_id":"e883f2789cae"},
2612
+ {"key":"L0151","section":"Preferred roles","text":"The kinds of work you prefer. Task suggestions lean toward your choices — pick one, several, or none.","placement":"placed","file":"modules/hall-ui/public/settings.html","line":116,"string_id":"9f45c63c9697"},
2613
+ {"key":"L0152","section":"Preferred roles","text":"Artist","placement":"unplaced"},
2614
+ {"key":"L0153","section":"Preferred roles","text":"Ideator","placement":"unplaced"},
2615
+ {"key":"L0154","section":"Preferred roles","text":"UI","placement":"unplaced"},
2616
+ {"key":"L0155","section":"Preferred roles","text":"Save","placement":"unplaced"},
2617
+ {"key":"L0156","section":"Preferred roles","text":"Saves when you press Save; your next","placement":"placed","file":"modules/hall-ui/public/settings.html","line":125,"string_id":"42cbc20a6ec8"},
2618
+ {"key":"L0157","section":"Preferred roles","text":"reflects it.","placement":"placed","file":"modules/hall-ui/public/settings.html","line":125,"string_id":"26da1df6fd4a"}
2579
2619
  ]
2580
2620
  },
2581
2621
  {
@@ -24,7 +24,9 @@
24
24
  const { escapeHtml, $ } = window.OTB;
25
25
  const toast = (msg) => window.OTB.toast(msg);
26
26
 
27
- const state = { rows: [], suggestions: [], openId: null, busy: false };
27
+ // `walk` is the skills walkthrough in progress, or null (task 1004073):
28
+ // { id, data, step, decisions, saving }. See walkHtml below.
29
+ const state = { rows: [], suggestions: [], openId: null, busy: false, walk: null };
28
30
 
29
31
  const el = (id) => document.getElementById(id);
30
32
  const statusLine = (msg) => { const s = el('specialities-status'); if (s) s.textContent = msg || ''; };
@@ -73,10 +75,148 @@
73
75
  </details>`;
74
76
  }
75
77
 
78
+ // ── THE SKILLS WALKTHROUGH (task 1004073; ADR 0310 §3) ────────────────────
79
+ //
80
+ // The owner's ruling: an adopted speciality's skills start OFF, "and you
81
+ // should walk through what comes with each, people need to learn the system".
82
+ // So this is deliberately NOT a list of checkboxes. It shows ONE skill at a
83
+ // time — what it does, when to reach for it, what it costs — and moves on only
84
+ // once the person has decided about that one. There is no "turn them all on"
85
+ // and no skip: the bar is that someone who finishes can say what each skill
86
+ // does, and a control that decides without reading defeats it.
87
+ //
88
+ // Nothing is written until the recap's "Save my choices", and that sends the
89
+ // WHOLE set (PUT replaces it), so walking away half-way leaves every skill off —
90
+ // the default the ruling asked for. Turning a skill on grants nothing: a
91
+ // rank-gated skill stays rank-gated, and the step says so before you choose.
92
+
93
+ const walkSteps = (w) => (w.data.skills || []).filter((k) => k.installed);
94
+
95
+ const RANK_COPY = {
96
+ metic: 'Only builders of Metic rank or above can run it. Turning it on here does not change that.',
97
+ archon: 'Only the project owner (Archon) can run it. Turning it on here does not change that.',
98
+ };
99
+
100
+ async function openWalk(id) {
101
+ try {
102
+ const data = await call('GET', `/specialities/${id}/skills`);
103
+ if (!data) return;
104
+ if (!walkSteps({ data }).length) { toast('This speciality offers no skills to choose.'); return; }
105
+ state.walk = { id: String(id), data, step: 0, decisions: {}, saving: false };
106
+ state.openId = null;
107
+ render();
108
+ focusWalk();
109
+ } catch (err) { statusLine(`Could not load its skills — ${err.message}`); }
110
+ }
111
+
112
+ // Each step replaces the panel's contents, so focus goes to the new heading —
113
+ // otherwise a keyboard or screen-reader user is left on a button that no
114
+ // longer exists. Focus only; nothing animates.
115
+ function focusWalk() {
116
+ const h = document.querySelector('.skill-walk [data-walk-focus]');
117
+ if (h) h.focus();
118
+ }
119
+
120
+ function stepHtml(w, k, i, total) {
121
+ const was = w.data.enabled.includes(k.name);
122
+ const decided = w.decisions[k.name];
123
+ const commands = (k.commands || []).length
124
+ ? ` You can also start it yourself by typing <code>${escapeHtml(k.commands[0])}</code>.` : '';
125
+ const guessed = k.derived && (k.derived.does || k.derived.cost)
126
+ ? '<p class="prow__hint skill-walk__note">These words come from the skill’s own description, which was written for Claude to recognise rather than for you to read — so a term may go unexplained.</p>'
127
+ : '';
128
+ return `
129
+ <p class="skill-walk__progress">Skill ${i + 1} of ${total} in ${escapeHtml(w.data.speciality.name)}</p>
130
+ <h4 class="skill-walk__name" tabindex="-1" data-walk-focus>${escapeHtml(k.name)}</h4>
131
+ <dl class="skill-walk__facts">
132
+ <dt>What it does</dt><dd>${escapeHtml(k.does || 'Its author gave no description.')}</dd>
133
+ <dt>When to reach for it</dt><dd>${escapeHtml(k.reachFor || 'Its author did not say.')}${commands}</dd>
134
+ <dt>What it costs</dt><dd>${escapeHtml(k.cost)}</dd>
135
+ ${(k.needs || []).length ? `<dt>What it needs on your machine</dt><dd>${k.needs.map((n) => `<code>${escapeHtml(n)}</code>`).join(', ')}</dd>` : ''}
136
+ ${k.rank && RANK_COPY[k.rank] ? `<dt>Who can run it</dt><dd>${RANK_COPY[k.rank]}</dd>` : ''}
137
+ </dl>
138
+ ${guessed}
139
+ ${was ? '<p class="prow__hint">You have this one on at the moment.</p>' : ''}
140
+ <div class="speciality-actions skill-walk__actions">
141
+ ${i > 0 ? '<button type="button" class="pbtn pbtn--quiet" data-walk="back">Back</button>' : ''}
142
+ <button type="button" class="pbtn" data-walk="off" aria-pressed="${decided === false}">Leave it off</button>
143
+ <button type="button" class="pbtn" data-walk="on" aria-pressed="${decided === true}">Turn it on</button>
144
+ </div>`;
145
+ }
146
+
147
+ function recapHtml(w, steps) {
148
+ const on = steps.filter((k) => w.decisions[k.name]).length;
149
+ const gone = (w.data.skills || []).filter((k) => !k.installed);
150
+ return `
151
+ <h4 class="skill-walk__name" tabindex="-1" data-walk-focus>Your choices for ${escapeHtml(w.data.speciality.name)}</h4>
152
+ <p class="prow__hint">${on} of ${steps.length} turned on. Each one, in a line:</p>
153
+ <ul class="skill-walk__recap">
154
+ ${steps.map((k) => `
155
+ <li>
156
+ <strong>${escapeHtml(k.name)}</strong>
157
+ <span class="speciality-badge${w.decisions[k.name] ? ' speciality-badge--on' : ''}">${w.decisions[k.name] ? 'on' : 'off'}</span>
158
+ <span class="prow__hint">${escapeHtml(firstSentence(k.does))}</span>
159
+ </li>`).join('')}
160
+ </ul>
161
+ ${gone.length ? `<p class="prow__hint">Also offered, but no longer on this project, so it cannot be turned on: ${gone.map((k) => `<code>${escapeHtml(k.name)}</code>`).join(', ')}.</p>` : ''}
162
+ <div class="speciality-actions skill-walk__actions">
163
+ <button type="button" class="pbtn pbtn--quiet" data-walk="restart">Go through them again</button>
164
+ <button type="button" class="pbtn pbtn--save" data-walk="save" ${w.saving ? 'disabled' : ''}>Save my choices</button>
165
+ </div>`;
166
+ }
167
+
168
+ function firstSentence(text) {
169
+ const t = String(text || '');
170
+ const m = /^(.+?[.!?])(\s|$)/.exec(t);
171
+ return m ? m[1] : t;
172
+ }
173
+
174
+ function walkHtml() {
175
+ const w = state.walk;
176
+ const steps = walkSteps(w);
177
+ const body = w.step < steps.length ? stepHtml(w, steps[w.step], w.step, steps.length) : recapHtml(w, steps);
178
+ return `<section class="skill-walk" aria-label="Choose the skills for ${escapeHtml(w.data.speciality.name)}">
179
+ ${body}
180
+ <button type="button" class="skill-walk__later" data-walk="close">Finish later — everything stays off until you save</button>
181
+ </section>`;
182
+ }
183
+
184
+ async function walkAct(action) {
185
+ const w = state.walk;
186
+ if (!w) return;
187
+ const steps = walkSteps(w);
188
+ if (action === 'close') { state.walk = null; render(); return; }
189
+ if (action === 'back') w.step = Math.max(0, w.step - 1);
190
+ if (action === 'restart') w.step = 0;
191
+ if ((action === 'on' || action === 'off') && w.step < steps.length) {
192
+ w.decisions[steps[w.step].name] = action === 'on';
193
+ w.step += 1;
194
+ }
195
+ if (action === 'save') {
196
+ w.saving = true;
197
+ render();
198
+ try {
199
+ const enabled = steps.filter((k) => w.decisions[k.name]).map((k) => k.name);
200
+ await call('PUT', `/specialities/${w.id}/skills`, { enabled_skills: enabled });
201
+ state.walk = null;
202
+ toast(`Saved — ${enabled.length} of ${steps.length} skill${steps.length === 1 ? '' : 's'} on.`);
203
+ await load();
204
+ return;
205
+ } catch (err) {
206
+ w.saving = false;
207
+ statusLine(`Could not save your choices — ${err.message}`);
208
+ }
209
+ }
210
+ render();
211
+ focusWalk();
212
+ }
213
+
76
214
  function cardHtml(s) {
77
215
  const trained = Number(s.documentCount || 0);
78
216
  const learned = Number(s.learningCount || 0);
79
217
  const open = String(state.openId) === String(s.id);
218
+ const offered = Array.isArray(s.skills) ? s.skills.length : 0;
219
+ const walking = state.walk && state.walk.id === String(s.id);
80
220
  return `
81
221
  <li class="prow speciality-card" data-id="${escapeHtml(String(s.id))}">
82
222
  <div class="prow__main">
@@ -91,15 +231,18 @@
91
231
  Trained on <strong>${trained}</strong> document${trained === 1 ? '' : 's'} you added
92
232
  · learned <strong>${learned}</strong> thing${learned === 1 ? '' : 's'} from your sessions
93
233
  · shared with: ${escapeHtml(VISIBILITY_COPY[s.visibility] || s.visibility || 'only you')}
234
+ ${offered ? `· offers <strong>${offered}</strong> skill${offered === 1 ? '' : 's'}${s.active ? `, <strong>${(s.enabled_skills || []).length}</strong> on for you` : ''}` : ''}
94
235
  </p>
95
236
  </div>
96
237
  <div class="prow__actions">
238
+ ${s.active && offered && !walking ? `<button type="button" class="btn btn--quiet" data-act="walk" data-id="${escapeHtml(String(s.id))}">Choose its skills</button>` : ''}
97
239
  ${s.mine ? `<button type="button" class="btn btn--quiet" data-act="train" data-id="${escapeHtml(String(s.id))}">${open ? 'Close' : 'Train'}</button>` : ''}
98
240
  ${s.active
99
241
  ? `<button type="button" class="btn btn--quiet" data-act="abandon" data-id="${escapeHtml(String(s.id))}">Stop using</button>`
100
242
  : `<button type="button" class="btn" data-act="adopt" data-id="${escapeHtml(String(s.id))}" ${s.adoptable ? '' : 'disabled'}>Use this</button>`}
101
243
  </div>
102
244
  ${open ? trainHtml(s) : ''}
245
+ ${walking ? walkHtml() : ''}
103
246
  </li>`;
104
247
  }
105
248
 
@@ -183,10 +326,18 @@
183
326
  ]);
184
327
  if (!cat) return;
185
328
  state.suggestions = (offered && offered.suggestions) || [];
186
- const activeIds = new Set(((mine && mine.adoptions) || []).filter((a) => a.active).map((a) => String(a.id)));
187
- state.rows = ((cat && cat.specialities) || []).map((s) => ({ ...s, active: activeIds.has(String(s.id)) }));
329
+ const active = new Map(((mine && mine.adoptions) || []).filter((a) => a.active).map((a) => [String(a.id), a]));
330
+ state.rows = ((cat && cat.specialities) || []).map((s) => {
331
+ const a = active.get(String(s.id));
332
+ return { ...s, active: !!a, enabled_skills: (a && a.enabled_skills) || [] };
333
+ });
188
334
  render();
189
335
  statusLine('');
336
+ // The section ships `hidden`, like every settings panel, and is revealed
337
+ // once its reads answer. Nothing revealed this one until task 1004073, so
338
+ // the panel — and adoption with it — was unreachable from the hall.
339
+ const section = el('specialities-scroll');
340
+ if (section) section.hidden = false;
190
341
  } catch (err) {
191
342
  statusLine(`Could not load specialities — ${err.message}`);
192
343
  }
@@ -197,8 +348,18 @@
197
348
  state.busy = true;
198
349
  try {
199
350
  if (action === 'adopt') { await call('POST', `/specialities/${id}/adopt`); toast('Using this speciality.'); }
200
- if (action === 'abandon') { await call('POST', `/specialities/${id}/abandon`); toast('Stopped using it.'); }
351
+ if (action === 'abandon') {
352
+ await call('POST', `/specialities/${id}/abandon`);
353
+ toast('Stopped using it.');
354
+ if (state.walk && state.walk.id === String(id)) state.walk = null;
355
+ }
201
356
  await load();
357
+ // Adopting is the moment the ruling is about: a speciality that offers
358
+ // skills opens straight into the walkthrough, with every one still off.
359
+ if (action === 'adopt') {
360
+ const row = state.rows.find((s) => String(s.id) === String(id));
361
+ if (row && Array.isArray(row.skills) && row.skills.length) await openWalk(id);
362
+ }
202
363
  } catch (err) {
203
364
  statusLine(err.message);
204
365
  } finally {
@@ -221,10 +382,13 @@
221
382
  const host = el('specialities-rows');
222
383
  if (host) {
223
384
  host.addEventListener('click', (e) => {
385
+ const walkBtn = e.target.closest('button[data-walk]');
386
+ if (walkBtn) { walkAct(walkBtn.dataset.walk); return; }
224
387
  const btn = e.target.closest('button[data-act]');
225
388
  if (!btn) return;
226
389
  const { act: action, id } = btn.dataset;
227
- if (action === 'train') { state.openId = String(state.openId) === String(id) ? null : id; render(); return; }
390
+ if (action === 'walk') { openWalk(id); return; }
391
+ if (action === 'train') { state.openId = String(state.openId) === String(id) ? null : id; state.walk = null; render(); return; }
228
392
  act(action, id);
229
393
  });
230
394