@augurworks/augur 0.15.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (190) hide show
  1. package/CANVAS.md +858 -0
  2. package/INSTALL.md +603 -0
  3. package/LICENSE +27 -0
  4. package/README.md +150 -0
  5. package/TRADEMARKS.md +72 -0
  6. package/agents/README.md +65 -0
  7. package/agents/canon-extract.md +117 -0
  8. package/agents/canon.md +151 -0
  9. package/agents/canvas.md +88 -0
  10. package/agents/currency.md +74 -0
  11. package/agents/drafts.md +92 -0
  12. package/agents/identity.md +148 -0
  13. package/agents/prototype-contract.md +69 -0
  14. package/agents/publishing.md +324 -0
  15. package/agents/review-feedback.md +76 -0
  16. package/agents/space-json.md +132 -0
  17. package/agents/ui-skill.md +101 -0
  18. package/agents/working-marks.md +86 -0
  19. package/brand/augur-eye.svg +3 -0
  20. package/brand/augur-icon.svg +41 -0
  21. package/brand/augur-mark.svg +5 -0
  22. package/brand/lentianova-bulky.otf +0 -0
  23. package/brand/lentianova-median.otf +0 -0
  24. package/brand/lentianova.woff2 +0 -0
  25. package/build.js +8409 -0
  26. package/changelog.md +133 -0
  27. package/fonts/inter-latin-wght-normal.woff2 +0 -0
  28. package/package.json +57 -0
  29. package/pitis/PETS.md +121 -0
  30. package/pitis/README.md +117 -0
  31. package/pitis/index.html +266 -0
  32. package/pitis/piti.build.js +81 -0
  33. package/pitis/piti.js +929 -0
  34. package/pitis/roast-agent.md +185 -0
  35. package/realtime/src/index.js +119 -0
  36. package/realtime/wrangler.example.toml +44 -0
  37. package/scripts/adopt.mjs +106 -0
  38. package/scripts/board-snapshot.mjs +197 -0
  39. package/scripts/build-seed-pack.mjs +33 -0
  40. package/scripts/bundle-rekey.mjs +112 -0
  41. package/scripts/bundle-tenancy-rehearsal.mjs +781 -0
  42. package/scripts/canon-extract.mjs +578 -0
  43. package/scripts/canon.mjs +599 -0
  44. package/scripts/canvas-screen.mjs +333 -0
  45. package/scripts/check-local.mjs +136 -0
  46. package/scripts/clawd-art.mjs +75 -0
  47. package/scripts/clawd-canvas.mjs +741 -0
  48. package/scripts/cli.mjs +100 -0
  49. package/scripts/clone.mjs +422 -0
  50. package/scripts/close.mjs +30 -0
  51. package/scripts/connect.mjs +103 -0
  52. package/scripts/deploy.mjs +157 -0
  53. package/scripts/dev.mjs +54 -0
  54. package/scripts/doc-lint.mjs +143 -0
  55. package/scripts/export.mjs +300 -0
  56. package/scripts/fork.mjs +64 -0
  57. package/scripts/freeze.mjs +74 -0
  58. package/scripts/frontdoor-parity.mjs +180 -0
  59. package/scripts/hook.mjs +67 -0
  60. package/scripts/identity-rekey.mjs +112 -0
  61. package/scripts/init.mjs +122 -0
  62. package/scripts/land.mjs +40 -0
  63. package/scripts/lib/adapters.mjs +156 -0
  64. package/scripts/lib/board-snapshot.mjs +511 -0
  65. package/scripts/lib/draft.mjs +385 -0
  66. package/scripts/lib/graduate.mjs +276 -0
  67. package/scripts/lib/instance.mjs +74 -0
  68. package/scripts/lib/marks.mjs +107 -0
  69. package/scripts/lib/materialize.mjs +138 -0
  70. package/scripts/lib/merge3.mjs +124 -0
  71. package/scripts/lib/offline-posture.mjs +120 -0
  72. package/scripts/lib/offline-respawn.mjs +18 -0
  73. package/scripts/lib/offline-wrangler.mjs +78 -0
  74. package/scripts/lib/publish-compose.mjs +12 -0
  75. package/scripts/lib/publish-conflict.mjs +78 -0
  76. package/scripts/lib/publish-evidence.mjs +144 -0
  77. package/scripts/lib/refine-compare.mjs +140 -0
  78. package/scripts/lib/refine-ledger.mjs +150 -0
  79. package/scripts/lib/refine-png.mjs +149 -0
  80. package/scripts/lib/seed-pack-build.mjs +141 -0
  81. package/scripts/lib/state-compare.mjs +68 -0
  82. package/scripts/lib/store.mjs +122 -0
  83. package/scripts/login.mjs +84 -0
  84. package/scripts/mark.mjs +112 -0
  85. package/scripts/migrate-board-keys.mjs +164 -0
  86. package/scripts/migrate.mjs +265 -0
  87. package/scripts/no-foreign-vocabulary.mjs +216 -0
  88. package/scripts/no-product-names.mjs +157 -0
  89. package/scripts/no-tenant-globals.mjs +1134 -0
  90. package/scripts/offline.mjs +247 -0
  91. package/scripts/og.mjs +170 -0
  92. package/scripts/one-tenant-resolver.mjs +146 -0
  93. package/scripts/open.mjs +63 -0
  94. package/scripts/publish.mjs +1041 -0
  95. package/scripts/read.mjs +31 -0
  96. package/scripts/refine.mjs +455 -0
  97. package/scripts/release-drift.mjs +138 -0
  98. package/scripts/restore.mjs +322 -0
  99. package/scripts/review.mjs +125 -0
  100. package/scripts/save.mjs +21 -0
  101. package/scripts/shell-lint.mjs +189 -0
  102. package/scripts/ship.mjs +460 -0
  103. package/scripts/shoot.mjs +264 -0
  104. package/scripts/smoke-invite.mjs +113 -0
  105. package/scripts/state-inventory.mjs +223 -0
  106. package/scripts/status.mjs +177 -0
  107. package/scripts/sync.mjs +27 -0
  108. package/scripts/tenant-do-rehearsal.mjs +1314 -0
  109. package/scripts/ui-copy-lint.mjs +202 -0
  110. package/scripts/watch.mjs +32 -0
  111. package/scripts/wrangler-preflight.mjs +246 -0
  112. package/seed/CANON.md +43 -0
  113. package/seed/README.md +119 -0
  114. package/seed/prototype-status.json +9 -0
  115. package/seed/registry.json +88 -0
  116. package/seed/skills/starter-ui/SKILL.md +52 -0
  117. package/seed/skills/starter-ui/skill.json +11 -0
  118. package/seed/skills/starter-ui/starter-tokens.css +73 -0
  119. package/seed/skills/starter-ui/starter-ui.css +318 -0
  120. package/seed/skills/starter-ui/starter-ui.js +50 -0
  121. package/seed/space.json +5 -0
  122. package/seed/start-here/prototypes/connect-your-terminal/index.html +428 -0
  123. package/seed/start-here/prototypes/connect-your-terminal/preview.webp +0 -0
  124. package/seed/start-here/prototypes/sample-with-comments/index.html +172 -0
  125. package/seed/start-here/prototypes/sample-with-comments/preview.webp +0 -0
  126. package/seed/start-here/prototypes/set-up-your-design-system/index.html +353 -0
  127. package/seed/start-here/prototypes/set-up-your-design-system/preview.webp +0 -0
  128. package/seed/threads.json +52 -0
  129. package/seed/worked-examples/prototypes/field-readings/index.html +273 -0
  130. package/seed/worked-examples/prototypes/field-readings/preview.webp +0 -0
  131. package/seed/worked-examples/prototypes/slide-deck/index.html +214 -0
  132. package/seed/worked-examples/prototypes/slide-deck/preview.webp +0 -0
  133. package/seed/worked-examples/prototypes/specimen-viewer/index.html +203 -0
  134. package/seed/worked-examples/prototypes/specimen-viewer/preview.webp +0 -0
  135. package/src/_worker.js +12668 -0
  136. package/src/board-key.mjs +57 -0
  137. package/src/board-room.mjs +881 -0
  138. package/src/bundle-keys.mjs +138 -0
  139. package/src/canon/collect-in-browser.js +215 -0
  140. package/src/canon/emit.mjs +232 -0
  141. package/src/canon/observe.mjs +260 -0
  142. package/src/canon/schema.mjs +451 -0
  143. package/src/canvas/DSEG-LICENSE.txt +95 -0
  144. package/src/canvas/DSEG7Classic-Bold.woff2 +0 -0
  145. package/src/canvas/canvas.css +885 -0
  146. package/src/canvas/canvas.js +5780 -0
  147. package/src/canvas/capture.js +485 -0
  148. package/src/chrome/appchrome.mjs +568 -0
  149. package/src/currency.mjs +203 -0
  150. package/src/delete-confirmation.mjs +254 -0
  151. package/src/drafts/drafts.js +326 -0
  152. package/src/entry.js +58 -0
  153. package/src/galleries.mjs +400 -0
  154. package/src/health-cron.mjs +173 -0
  155. package/src/identity.json +1 -0
  156. package/src/kv-codec.mjs +135 -0
  157. package/src/kv-identity.mjs +259 -0
  158. package/src/mail.mjs +599 -0
  159. package/src/provenance.mjs +74 -0
  160. package/src/publish-compose.mjs +363 -0
  161. package/src/publish-fork.mjs +221 -0
  162. package/src/publish-units.mjs +44 -0
  163. package/src/purge.mjs +81 -0
  164. package/src/review/COMMENTING-UX.md +306 -0
  165. package/src/review/cat.png +0 -0
  166. package/src/review/comment-cursor.svg +7 -0
  167. package/src/review/comments.js +1738 -0
  168. package/src/room-ticket.mjs +96 -0
  169. package/src/roster-chip.mjs +32 -0
  170. package/src/seed-pack.mjs +261 -0
  171. package/src/state-inventory.mjs +249 -0
  172. package/src/sw-logic.mjs +48 -0
  173. package/src/tenant-cache.mjs +141 -0
  174. package/src/tenant-context.mjs +386 -0
  175. package/src/tenant-do.js +2940 -0
  176. package/src/tenant-host.mjs +144 -0
  177. package/src/tenant-quotas.mjs +140 -0
  178. package/src/unit-core.mjs +103 -0
  179. package/src/unit-object.mjs +338 -0
  180. package/templates/README.md +67 -0
  181. package/templates/shell/deploy.yml +145 -0
  182. package/templates/shell/engine-bump.yml +142 -0
  183. package/templates/shell/health.yml +233 -0
  184. package/templates/shell/kv-backup.yml +201 -0
  185. package/templates/shell/roster-update.yml +110 -0
  186. package/templates/shell/space-preflight.yml +35 -0
  187. package/templates/shell/space-rebake.yml +79 -0
  188. package/templates/shell/store-backup.yml +152 -0
  189. package/templates/shell/wrangler.example.toml +266 -0
  190. package/templates/space/publish.yml +91 -0
package/changelog.md ADDED
@@ -0,0 +1,133 @@
1
+ # Augur changelog
2
+
3
+ What's new in Augur, for the people who use it. Newest goes on top.
4
+
5
+ **Only things you can see belong here.** A new thing you can do, a screen that
6
+ works better, something that used to be annoying and isn't. Not bug fixes, not
7
+ plumbing, not decisions about how the code is arranged — nobody comes to this
8
+ page for those.
9
+
10
+ **Format (one entry):**
11
+
12
+ ```
13
+ ## 2026-06-20 — Short title
14
+ One or two short sentences a kid could read. Say what you can do now, and why
15
+ that's nice. No jargon.
16
+ ```
17
+
18
+ The date is the day the update went live. The page works out "Today / 3 days ago /
19
+ 2 weeks ago…" by itself, so you never have to touch old entries.
20
+
21
+ ---
22
+
23
+ ## 2026-09-03 — Your agent finds the door on its own
24
+ Point an agent at a workspace address and it now learns how to get in without
25
+ asking you for a password: the site tells it to run `augur connect`, you approve a
26
+ code in your browser, and it can publish. Before, every locked page looked the same
27
+ to it, and it went hunting for credentials.
28
+
29
+ ## 2026-09-03 — Your edit lands at its own address
30
+ Publishing a page you changed puts it at its address, even when someone before
31
+ you published from an unsaved folder. Before, that could send your page to a
32
+ "-conflict" copy instead, and the copies piled up. Now a copy is made only when
33
+ two people really changed the same page, and it goes away by itself once the
34
+ change is at the real address.
35
+
36
+ ## 2026-08-25 — Send an invite by email
37
+ Adding someone used to mean copying a link out of the Admin page and sending it
38
+ yourself. Now Augur can email it for you. You still get the link either way, so
39
+ you can send it your own way if you'd rather.
40
+
41
+ ## 2026-08-19 — Cards show everyone who worked on something
42
+ A card used to show one face: whoever saved it last. Now it shows all of them.
43
+
44
+ ## 2026-08-19 — Links look like your site
45
+ Paste an Augur link into a chat or a document and you get a proper preview card,
46
+ with your own name, description and picture on it. A link to a canvas shows a
47
+ picture of the board.
48
+
49
+ ## 2026-08-18 — Pages open instantly
50
+ The parts every page shares — the sidebar, the header — are now loaded once and
51
+ kept ready. Clicking around is close to instant.
52
+
53
+ ## 2026-08-17 — Augur on your phone
54
+ Augur has a real phone layout now: a tab bar at the bottom you can reach with
55
+ your thumb, a header that says where you are and how to get back, and Pinned and
56
+ Profile sliding up from the bottom. Search sits in the tab bar.
57
+
58
+ ## 2026-08-16 — A home for your workspace
59
+ Admin is its own place in the sidebar now. Open it to see who's in your
60
+ workspace, what's live, and the settings — including a workspace picture you can
61
+ change like a profile photo. You can change someone's role right from their row
62
+ in the list, and each role has its own mark, so admin, editor and viewer are easy
63
+ to tell apart. The Library is now called the Design system, because that's what
64
+ it is.
65
+
66
+ ## 2026-08-16 — Galleries use the whole window
67
+ Grids of prototypes and projects used to stop at a fixed width and leave a wide
68
+ screen half empty. They now add columns as the window grows, so a big screen
69
+ shows more work instead of more background.
70
+
71
+ ## 2026-08-14 — A viewer role
72
+ You can now invite someone who signs in, reads, comments and joins a canvas, but
73
+ can never publish. Handy for a client or a colleague you want in the conversation
74
+ without handing them the keys.
75
+
76
+ ## 2026-08-12 — Change ten things at once on a canvas
77
+ Select a pile of stickies and pick a colour: they all change. Same for text size,
78
+ bold, italic and alignment. The toolbar only offers a control when everything you
79
+ picked is the same kind of thing, so one click never does ten different things.
80
+
81
+ ## 2026-08-12 — Arrow keys nudge things on a canvas
82
+ Select anything on a board — a sticky, a prototype, a bit of text, a whole
83
+ section — and the arrow keys move it one step at a time. Hold Shift to move it
84
+ ten steps. It's what you want when something is nearly, but not quite, lined up.
85
+
86
+ ## 2026-08-12 — A prototype on a canvas stays where you left it
87
+ Scroll a prototype on a board while you're using it and the board keeps that
88
+ view. It's what everyone else sees from then on, and what's waiting for you
89
+ tomorrow, until the next person scrolls it somewhere else.
90
+
91
+ ## 2026-08-12 — Set your own profile photo
92
+ Open the menu under your name and pick "Add photo". Your face shows up on your
93
+ chip, on your comments, and next to your cursor when you're on a canvas with
94
+ someone. Change it or remove it whenever you like — it's yours.
95
+
96
+ ## 2026-08-11 — Comment pins open when you point at them
97
+ Point at a comment pin and it opens itself, so you don't have to click first.
98
+ Move onto the card to read it, click it to open the thread, or drag it to move
99
+ the comment. Stamps on a canvas land smaller now, with a sharp white edge instead
100
+ of a blurry one.
101
+
102
+ ## 2026-08-09 — Invite and remove people
103
+ The people list is a table now: who they are, what they're allowed to do, and
104
+ when they were last here. "Invite" at the top right takes an email and gives you
105
+ a single-use link to send them. Click anyone to reset their password or remove
106
+ them.
107
+
108
+ ## 2026-08-07 — New canvases are shareable right away
109
+ A canvas made with the "+ New canvas" button opens for anyone with the link,
110
+ just like a published prototype — no sign-in needed. Before, only signed-in
111
+ teammates could see it.
112
+
113
+ ## 2026-08-06 — Pick a card's status in one go
114
+ Hover the little status dot on a card and a menu opens, so you jump straight to
115
+ the state you want instead of clicking through the others. Cards also wait until
116
+ you move away before they re-sort, so nothing hops around while you're setting
117
+ them.
118
+
119
+ ## 2026-06-22 — Your own account
120
+ Augur has real logins. Sign in with your own email and password instead of one
121
+ shared site password, and you get your own profile in the top-left corner: your
122
+ name, your picture, and your own pinned prototypes. Statuses, names and comments
123
+ stay shared, because those are team decisions.
124
+
125
+ ## 2026-06-21 — Blocks update everywhere at once
126
+ Every building block on a page is now a live copy of one master. Improve the
127
+ master and every page using it improves too — no stale copies quietly drifting
128
+ apart. Want a block to be different in one place? Detach it and you get your own
129
+ copy to edit, marked so everyone can see it no longer follows the master.
130
+
131
+ ## 2026-06-19 — New name and look: Augur
132
+ The prototyping tool got a proper name and a face — Augur, with the
133
+ eye-and-sparkle logo you see in the top-left corner.
package/package.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "@augurworks/augur",
3
+ "version": "0.15.1",
4
+ "description": "A prototype and research repository for product teams. Real, clickable prototypes and the design system they are built from, on one site with login, comments and live boards on top. Underneath it is all git and static HTML.",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/andratwiro/augur.git"
9
+ },
10
+ "homepage": "https://github.com/andratwiro/augur#readme",
11
+ "publishConfig": {
12
+ "access": "public"
13
+ },
14
+ "type": "module",
15
+ "bin": {
16
+ "augur": "scripts/cli.mjs"
17
+ },
18
+ "files": [
19
+ "scripts/",
20
+ "build.js",
21
+ "src/",
22
+ "templates/",
23
+ "brand/",
24
+ "fonts/",
25
+ "agents/",
26
+ "seed/",
27
+ "pitis/",
28
+ "realtime/",
29
+ "INSTALL.md",
30
+ "CANVAS.md",
31
+ "TRADEMARKS.md",
32
+ "changelog.md"
33
+ ],
34
+ "scripts": {
35
+ "test": "node --test \"test/*.test.mjs\"",
36
+ "smoke": "node scripts/smoke-invite.mjs",
37
+ "build": "node build.js",
38
+ "shoot": "node scripts/shoot.mjs",
39
+ "shoot:stale": "node scripts/shoot.mjs --stale",
40
+ "og": "node scripts/og.mjs",
41
+ "og:stale": "node scripts/og.mjs --stale",
42
+ "review": "node scripts/review.mjs",
43
+ "refine": "node scripts/refine.mjs",
44
+ "dev": "node build.js && npx --yes serve dist",
45
+ "offline": "node scripts/offline.mjs",
46
+ "deploy": "node scripts/deploy.mjs",
47
+ "deploy:realtime": "set -a && . ./.env.deploy && set +a && npx wrangler deploy realtime/src/index.js -c \"${REALTIME_CONFIG:?set it in .env.deploy — path to the realtime.wrangler.toml in your deploy shell (see realtime/wrangler.example.toml)}\"",
48
+ "posters": "node scripts/shoot.mjs --stale && node scripts/og.mjs --stale",
49
+ "check": "node scripts/check-local.mjs"
50
+ },
51
+ "engines": {
52
+ "node": ">=18"
53
+ },
54
+ "devDependencies": {
55
+ "playwright": "^1.60.0"
56
+ }
57
+ }
package/pitis/PETS.md ADDED
@@ -0,0 +1,121 @@
1
+ # Pitis — the pet-drawing spec
2
+
3
+ Everything about how the **pitis** (the cursor-pet layer) are drawn, so an agent
4
+ can extend the lineup without re-deriving anything. The companion engine lives
5
+ entirely in `pitis/` (see README.md).
6
+
7
+ ## The lineup (species + looks)
8
+
9
+ ### Ginger & white — bicolor cat · CAT pattern `bicolor` (cat-only)
10
+ - **Look:** white-dominant ginger bicolor. Orange cap over the head + ears, orange
11
+ patches on the back (shoulder + rump), ginger tail, **white face with a forehead
12
+ blaze**, white chest/belly/legs, pink nose.
13
+ - **Piti:** `PALETTE` entry **"Ginger & white"**, `pattern:'bicolor'`, cat-only.
14
+ Drawn by `bicolorMarks()` in `piti.js` (white base fur + clipped ginger patches +
15
+ pink nose + white blaze). **First in the cat colour picker.**
16
+
17
+ ### Tabby — grey/brown tabby cat · CAT pattern `tabby` (cat-only)
18
+ - **Look:** brown-grey **mackerel tabby**. Warm grey-brown base, darker brown/black
19
+ mackerel stripes (vertical ribs down back/sides), cream belly + chest, tabby
20
+ forehead "M", dark tail rings, pinkish nose.
21
+ - **Piti:** `PALETTE` entry **"Tabby"**, cat-only pattern; **replaces the cat's plain
22
+ grey**. Second in the cat picker. Anchors used: fur ~`#9C8C76`,
23
+ stripe ~`#4A4038`, belly ~`#D9CDB6`. (Confirm exact values in `piti.js`.)
24
+
25
+ ### Fawn — Spanish mastiff · SPECIES `mastiff` *(traced from a clean flat-tone illustration)*
26
+ - **Look:** big fawn/tan mastiff, curled tightly asleep. Dark-brown muzzle **mask**,
27
+ droopy dark-brown **ears**, furrowed **brow**, closed sleepy eyes, dark nose, pink
28
+ **blush** cheeks, faint tabby **stripe ticks** on the haunch, and a **black harness**
29
+ strap with a loop across the shoulder. Compact curl (head low-left on the front paws,
30
+ body curving up-right, tail curling back along the bottom).
31
+ - **Ref:** a CLEAN flat-tone illustration (756×534, local-only reference — not a
32
+ photo). Because the tones are flat/separable, the proper **layered-potrace
33
+ pipeline works** — no guide-mask hack needed.
34
+ - **Piti:** species **`mastiff`** in the resting curl. **≥30% bigger than the cat**
35
+ (~1.35×). Third species tab; wears hats via `HAT_T_MASTIFF`. **Three TRACED layers**
36
+ in one shared potrace frame **3024×2136** (`MTT = translate(0,2136) scale(0.1,-0.1)`),
37
+ all from that illustration with the green grass oval dropped (the stage draws its own):
38
+ `MASTIFF_P.sil` = full body silhouette → fawn fur (derived by **flood-filling the
39
+ interior of the outline line-art**, NOT by tone-thresholding — a threshold mask lets a
40
+ grass-oval footprint leak in as a fawn "floor" slab under the dog; filling the closed
41
+ outline excludes the grass by construction); `MASTIFF_P.brown` = dark-brown
42
+ mask + droopy ears + brow ridge + haunch stripe ticks (clipped to sil); `MASTIFF_P.outline`
43
+ = the chunky near-black hand-drawn line — body contour, **closed-eye arcs + nose + brow
44
+ furrow** (baked in), the **black harness** strap + loop, paw lines — drawn on top.
45
+ The pink **blush** has no hard edge so it's positioned (`blushL/R` ovals, upright frame,
46
+ clipped to sil). **Awake** = fawn lids painted over the eye area + open round eyes
47
+ (`eyeL/R`). Pipeline: flood-fill the grass → silhouette mask; threshold bands
48
+ (<13% black harness/nose, 13–55% brown mask/ears, <30% the outline line-art) → potrace
49
+ each at the SAME dims so one transform maps them. **CLIP GOTCHA:** transform on the
50
+ `<path>` inside `<clipPath>`, never a wrapping `<g>`. Fixed "Fawn" look (ignores the
51
+ recolour palette; `PALETTE` "Fawn" carries fur `#CE9D66`, brown mask `#5F4F40`,
52
+ blush `#E4AC93`, line `OUT`).
53
+
54
+ ### The base cat
55
+ - **Cat** (default species) — traced from reference sleeping-cat art; default
56
+ colour is the ginger bicolor. Cat picker holds **two cats**: Ginger & white
57
+ (bicolor) then Tabby. The lineup is **the two cats + the mastiff**; `loadConfig`
58
+ maps any saved `species:'dog'` config (a retired species id) to `'mastiff'`.
59
+
60
+ ## Architecture (how a piti is made)
61
+ - **`piti.js`** = the whole engine. `window.Piti = { PALETTE, HATS, svg, loadConfig,
62
+ saveConfig, mount, auto, reveal, hide, toggle, refreshLive }`. `config = {name,
63
+ furIdx, hat, species}`. Traced potrace paths per species (`P` cat, `MASTIFF_P`
64
+ mastiff). `petBody(species,…)` assembles; `svg(config,state)` renders.
65
+ Markings = `normalMarks` / `bicolorMarks` / `tabbyMarks`, drawn
66
+ **clipped to the silhouette**. **CLIP GOTCHA:** put the transform on the `<path>`
67
+ inside `<clipPath>`, never a wrapping `<g>` (Chrome silently mis-clips otherwise).
68
+ - **Per-pet patterns are cat-only**, guarded in `petBody` + filtered in the
69
+ customizer's `colourIndices()` (`index.html`). The bicolor sorts first.
70
+ - **Hats:** `HAT_T_CAT` / `HAT_T_MASTIFF` place hats on each crown
71
+ (measured off coordinate-grid renders). 5 hats: sprout, top hat, wizard, beanie, party.
72
+ - **Behaviours:** eased cursor-follow + catch-up; idle→sit→sleep("z"); pop-in;
73
+ startled hop + "!" on clicking links/cards; sweat "running" + **after-image trail**
74
+ on big fast moves (`dist > 165`); **custom arrow cursor** while active (`html.piti-cursor`).
75
+ - **Wiring (`piti.build.js`, an optional addon `build.js` loads):** copies `pitis/` →
76
+ dist, injects the loader into the shell + every prototype (skips preview iframes),
77
+ adds the footer paw. The paw opens the **customizer as an overlay modal** over the
78
+ dimmed site (`piti.js openModal()` → iframe of `/pitis/`); it **auto-saves** every
79
+ change and closes on **click-outside / Esc**. **Shift+Ñ** toggles the piti anywhere.
80
+ - **Self-contained:** nothing outside `pitis/` references it except one optional
81
+ `import` in `build.js`. Keep it that way.
82
+
83
+ ## Roast mode (the talking piti)
84
+ A **terminal agent** can drive the cat as a live design wingman ("roast mode"): it reads which prototype
85
+ you're on and, now and then, the cat **walks to an element, says one short UX/a11y remark,
86
+ waits ~3–5s, then returns to the cursor**. Voice = an advocate for people with **low
87
+ comprehension for screens** (the nervous first-timer, not the power user); bold but always
88
+ true. **Live only · prototypes + `/playground/` only · only while active (Shift+Ñ).**
89
+ - **Bridge:** `src/_worker.js` `pitiApi()` → `/__piti`, KV keys `pt:view` (browser → what
90
+ it's viewing) + `pt:remarks` (agent → quips, id = `Date.now()`, pruned at 3 min). Browser
91
+ ops open; agent read-view/write-remark reuse `REVIEW_EXPORT_KEY` (no new secret). This is
92
+ the one out-of-`pitis/` touch, and the worker already names piti (`/piti.js` whitelist), so
93
+ it's consistent — keep all *logic* in `pitis/`.
94
+ - **Client:** wingman channel inside `piti.js` `mount()` — `isCommentable()`, `publishView()`,
95
+ `pollRemarks()`, `startComment()` and a travel→speak→dwell→return state machine in `frame()`;
96
+ worded bubble `.piti-says` (resolves the target by CSS selector, falls back to rescaled
97
+ viewport coords). Cleaned up in `destroy()`.
98
+ - **Agent brief:** `pitis/roast-agent.md` (persona, low-comprehension checklist, the loop,
99
+ cadence/restraint, the full `/__piti` payload). Run from an agent terminal while building.
100
+
101
+ ## Working discipline (do not skip)
102
+ - **Verify every visual by rendering with headless Chrome and reading the PNG
103
+ against local reference imagery — never eyeball-grade your own SVG.**
104
+ Chrome: `"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
105
+ --headless --disable-gpu --hide-scrollbars --force-device-scale-factor=2
106
+ --window-size=W,H --screenshot=OUT.png "file://ABS.html"`.
107
+ - Free-mode design craft — no `.gv-*`, no space UI kit. `node build.js` must stay
108
+ green. Commit only `pitis/` paths (never `git add -A`).
109
+
110
+ ## Recipe — adding a new pet
111
+ - **New cat colour/marking:** add a `PALETTE` entry + a marks function (cat-only),
112
+ slot it into the picker order. Model real anchors off a photo (sample with magick).
113
+ - **New species:** trace the resting pose from a photo (the layered-potrace pipeline
114
+ described for the mastiff above), add a `petBody` branch + species tab +
115
+ `HAT_T_<species>` + size.
116
+ - Always render-compare against the reference in a loop until it reads as the animal.
117
+
118
+ ## References
119
+ - A local `reference/` dir (gitignored, never shipped) holds the pose/colour
120
+ reference imagery, behaviour clips and scratch render harnesses (`_*.html`/`_*.png`)
121
+ used while tracing. It is a working area, not part of the repo.
@@ -0,0 +1,117 @@
1
+ # Piti 🐾
2
+
3
+ A little companion that trails your cursor around the prototypes site — the
4
+ **pitis**: customizable cursor pets. A small delight layer that never gets taken
5
+ away.
6
+
7
+ Not a prototype, not a product thing — an aside. **Self-contained in `pitis/`:**
8
+ the rest of the repo doesn't know it exists. `build.js` only references it through a
9
+ single **optional addon import** (`pitis/piti.build.js`) + generic hooks; remove the
10
+ folder and the site builds identically. Keep it that way — don't reference piti from
11
+ general repo files (CLAUDE.md, build.js logic, shared CSS, agent memory, etc.).
12
+
13
+ ## Summon / dismiss
14
+ - **Shift + Ñ** anywhere toggles the piti on/off. Remembered per-browser via
15
+ `localStorage['piti-revealed']` (there is **no** typed secret). While active, the
16
+ whole page uses a **custom arrow cursor** (dark arrow + white outline; `html.piti-cursor`).
17
+ - A quiet, chrome-styled **paw in the site footer** (the addon's `footerHtml()`) opens
18
+ the **customizer** as an in-page **overlay modal** over the dimmed site (piti.js
19
+ `openModal()` loads `/pitis/` in an iframe). Direct `/pitis/` visits work standalone.
20
+ - **Admin-only, identity-gated.** Summoning requires a signed-in **admin** — `auto()`
21
+ checks `/__me` (or an instance with no user accounts at all: `accounts:false`, nobody
22
+ to hide it from). A signed-in teammate or a signed-out visitor on a public prototype
23
+ can press the combo all day and gets nothing; a stale `piti-revealed` flag in their
24
+ browser is cleared on the next page. Fails closed if `/__me` fails. Identity is only
25
+ asked for when it can change something (a pal already revealed here, or the combo
26
+ pressed) — a customer opening a public prototype costs no extra request.
27
+ The paw is separately hidden behind `html.gv-admin`.
28
+ ⚠️ The hotkey matches the **ñ character only**, never `e.code === "Semicolon"` — that
29
+ key is `;` on a US/AZERTY layout, so matching it summons a permanent pink cat for
30
+ anyone typing a colon.
31
+
32
+ ## What it does
33
+ - **Follows the cursor** — eased trailing follow with a catch-up boost and a smooth
34
+ facing flip.
35
+ - **Two species** — **cat** (default) and **mastiff**, both traced from reference
36
+ art of resting animals in the same pipeline. The piti only
37
+ exists in the resting/lying pose; `awake` just opens the eyes (awake while travelling,
38
+ sleepy when settled).
39
+ - **Recolour + hats** — the cat recolours, with two real-cat patterns in the picker:
40
+ **"Ginger & white"** (bicolor) and **"Tabby"** (mackerel tabby).
41
+ The mastiff is a fixed fawn look. 5 hats: sprout, top hat, wizard, beanie, party.
42
+ - **Behaviours / emotions** — idle → sit → (after ~11s) sleep with a "z"; a **pop-in**
43
+ when summoned; a **startled hop + "!"** when you click a link/card; a
44
+ **sweat-drop "running"** state + a faint
45
+ **after-image trail** (fading ghost copies) when it lags a fast cursor; the
46
+ occasional heart.
47
+ - **Follows INTO prototypes**, not just the nav. Never blocks the UI
48
+ (`pointer-events:none`), respects `prefers-reduced-motion`.
49
+
50
+ No feeding and no photobooth — deliberately out of scope.
51
+
52
+ ## Roast mode (the talking piti)
53
+ The piti can be driven by a **terminal agent** that watches what you're looking at and,
54
+ now and then, has the cat **walk to a spot on the screen, drop one short snarky UX/a11y
55
+ remark, hover ~3–5s, then return to the cursor** — a design wingman roasting your screen on
56
+ behalf of users with low comprehension for screens (snark is the delivery; the point is
57
+ always true). Self-contained: two KV keys on the live site + the agent brief.
58
+ - **Live only, prototypes + playground only, and only while active (Shift+Ñ).** The cat
59
+ polls `/__piti` for remarks just on `/…/prototypes/…` and `/playground/…` pages.
60
+ - **Bridge:** `src/_worker.js` `pitiApi()` exposes `/__piti` over KV keys `pt:view`
61
+ (browser publishes the page it's on) and `pt:remarks` (agent posts quips). Browser ops are
62
+ open; agent read-view / write-remark reuse the existing `REVIEW_EXPORT_KEY` secret — **no
63
+ new secret to provision**. The worker is the one sanctioned edge touch (same as it already
64
+ whitelists `/piti.js`); everything else lives in `pitis/`.
65
+ - **Client:** the wingman channel in `piti.js` `mount()` — `publishView()`, `pollRemarks()`,
66
+ and a travel→speak→dwell→return state machine; the worded bubble is `.piti-says`.
67
+ - **The agent:** see **`roast-agent.md`** — persona, the low-comprehension lens, the loop
68
+ (read view → read local source + screenshot live URL → compose ONE quip → POST), cadence
69
+ and restraint rules. Run it from an agent terminal (`/loop` self-paced) while you build.
70
+
71
+ ## Files (everything lives in `pitis/`)
72
+ - **`piti.js`** — the whole engine (one source of truth). Exposes
73
+ `window.Piti = { PALETTE, HATS, svg, loadConfig, saveConfig, mount, auto, reveal,
74
+ hide, toggle, refreshLive }`. Cat art = potrace paths `P.{sil,outMain,eyeL,eyeR,nose}`;
75
+ mastiff art = `MASTIFF_P` (traced silhouette + clipped overlays). `petBody(species,…)`
76
+ assembles a piti; `svg(config,state)` is the public render (config = `{name, furIdx,
77
+ hat, species}`, defaults to cat). Markings = `normalMarks` / `bicolorMarks` /
78
+ `tabbyMarks`, clipped to the silhouette. `hatSVG(id, species)` positions a hat
79
+ on the per-species crown (`HAT_T_CAT` / `HAT_T_MASTIFF`, measured off grid renders).
80
+ `mount()` = the
81
+ trailing companion (`{el, destroy, refresh}`); `auto()` = site manager (mounts when
82
+ revealed, wires Shift+Ñ, **skips inside iframes** so previews stay piti-free). CSS
83
+ classes are `piti-*` / `pt-*`.
84
+ - **`piti.build.js`** — the build-time addon (all of piti's `build.js` footprint).
85
+ Exports generic hooks: `transformHtml(html, v)` (inject the loader into copied
86
+ prototype/page/demo HTML; skips pages that already load `piti.js`), `bodyScripts()`
87
+ + `footerHtml()` + `css()` (for the generated shell pages), and `emit(ctx)` (copy
88
+ `pitis/` → `/dist/pitis/` and the engine to `/dist/piti.js`). `build.js` loads this
89
+ via one optional `import("./pitis/piti.build.js")` and calls the hooks — nothing
90
+ else in `build.js` mentions piti.
91
+ - **`index.html`** — the customizer: **species
92
+ tabs (cat/mastiff)** on top, the piti on a grass stage with **four chevrons (top pair
93
+ cycles hat, bottom pair cycles colour)**, a colour swatch row, name box. No title,
94
+ no Save (every change **auto-saves** + summons the piti), closes by **clicking
95
+ outside** (or Esc). Loads its own `piti.js`.
96
+ - A local **`reference/`** dir — source imagery, **gitignored & never shipped**:
97
+ pose/colour reference imagery, behaviour clips, plus scratch render harnesses
98
+ (`_*.html` / `_*.png`). A working area, not part of the repo.
99
+ - **`roast-agent.md`** — the brief that turns a terminal agent into the *talking* piti
100
+ (roast mode above). Persona + loop + the `/__piti` contract.
101
+
102
+ ## Working discipline (important)
103
+ - **Verify visuals by rendering with headless Chrome and reading the PNG against
104
+ the local reference imagery — never eyeball-grade your own SVG.**
105
+ - **Clip gotcha:** inside `<clipPath>`, put the transform on the `<path>` directly,
106
+ not on a wrapping `<g>` (Chrome only partially honours the `<g>` form and silently
107
+ mis-clips the markings).
108
+ - Free-mode bespoke build — **not** product UI, no `.gv-*` classes, exempt
109
+ from any space UI-kit lint.
110
+
111
+ ## Colours (PALETTE order)
112
+ Blossom (pink, default) · Sunset (orange) · Ink (black = warm grey) · Sunbeam
113
+ (yellow) · Meadow (olive) · Sky (blue) · Iris (purple) · Bubblegum (magenta) · Pebble
114
+ (grey) · **Ginger & white** (cat-only bicolor) · **Tabby** (cat-only mackerel
115
+ tabby) · **Fawn** (mastiff-only fixed look). Body fills are paler than the real
116
+ selector swatches (matched to real art). The cat picker shows only Ginger & white +
117
+ Tabby; the mastiff picker shows only Fawn.