@rubytech/create-maxy-code 0.1.478 → 0.1.479
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/package.json +1 -1
- package/payload/platform/docs/superpowers/plans/2026-07-20-task-1789-reseat-channel-row-fork.md +1244 -0
- package/payload/platform/docs/superpowers/plans/2026-07-20-task-1818-loop-gate-app-routes.md +462 -0
- package/payload/platform/docs/superpowers/plans/2026-07-20-task-1819-top-level-label-allowlist.md +321 -0
- package/payload/platform/docs/superpowers/plans/2026-07-20-task-1831-data-portal-class-derived-allowlist.md +2177 -0
- package/payload/platform/docs/superpowers/specs/2026-07-20-task-1789-reseat-channel-row-fork-design.md +201 -0
- package/payload/platform/docs/superpowers/specs/2026-07-20-task-1818-loop-gate-app-routes-design.md +217 -0
- package/payload/platform/docs/superpowers/specs/2026-07-20-task-1819-top-level-label-allowlist-design.md +80 -0
- package/payload/platform/docs/superpowers/specs/2026-07-20-task-1831-data-portal-class-derived-allowlist-design.md +163 -0
- package/payload/platform/lib/graph-style/dist/index.d.ts.map +1 -1
- package/payload/platform/lib/graph-style/dist/index.js +22 -0
- package/payload/platform/lib/graph-style/dist/index.js.map +1 -1
- package/payload/platform/lib/graph-style/src/__tests__/parity.test.ts +6 -0
- package/payload/platform/lib/graph-style/src/index.ts +20 -0
- package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +13 -1
- package/payload/platform/plugins/cloudflare/PLUGIN.md +26 -1
- package/payload/platform/plugins/cloudflare/bin/d1-http.mjs +80 -0
- package/payload/platform/plugins/cloudflare/bin/portal-enrol.mjs +17 -2
- package/payload/platform/plugins/cloudflare/bin/portal-index-push.mjs +357 -0
- package/payload/platform/plugins/cloudflare/bin/schema-exposed-dirs.mjs +103 -0
- package/payload/platform/plugins/cloudflare/mcp/__tests__/authorize.test.ts +2 -2
- package/payload/platform/plugins/cloudflare/mcp/__tests__/d1-http.test.ts +96 -0
- package/payload/platform/plugins/cloudflare/mcp/__tests__/portal-directory-listing.test.ts +120 -0
- package/payload/platform/plugins/cloudflare/mcp/__tests__/portal-enrol.test.ts +59 -4
- package/payload/platform/plugins/cloudflare/mcp/__tests__/portal-index-push.test.ts +176 -0
- package/payload/platform/plugins/cloudflare/mcp/__tests__/portal-index-state-contract.test.ts +75 -0
- package/payload/platform/plugins/cloudflare/mcp/__tests__/portal-indexed-download.test.ts +131 -0
- package/payload/platform/plugins/cloudflare/mcp/__tests__/portal-sign.test.ts +68 -0
- package/payload/platform/plugins/cloudflare/mcp/__tests__/schema-exposed-dirs.test.ts +88 -0
- package/payload/platform/plugins/cloudflare/mcp/__tests__/template-config.test.ts +39 -0
- package/payload/platform/plugins/cloudflare/skills/data-portal/SKILL.md +68 -1
- package/payload/platform/plugins/cloudflare/skills/data-portal/schema.sql +30 -1
- package/payload/platform/plugins/cloudflare/skills/data-portal/template/functions/api/_lib/portal-sign.mjs +87 -0
- package/payload/platform/plugins/cloudflare/skills/data-portal/template/functions/api/_lib/session.ts +8 -4
- package/payload/platform/plugins/cloudflare/skills/data-portal/template/functions/api/_lib/types.ts +10 -0
- package/payload/platform/plugins/cloudflare/skills/data-portal/template/functions/api/download.ts +107 -1
- package/payload/platform/plugins/cloudflare/skills/data-portal/template/functions/api/files.ts +82 -2
- package/payload/platform/plugins/cloudflare/skills/data-portal/template/index.html +9 -0
- package/payload/platform/plugins/cloudflare/skills/data-portal/template/portal.css +56 -0
- package/payload/platform/plugins/cloudflare/skills/data-portal/template/portal.js +98 -2
- package/payload/platform/plugins/cloudflare/skills/data-portal/template/wrangler.toml +12 -0
- package/payload/platform/plugins/docs/references/cloudflare.md +12 -0
- package/payload/platform/plugins/scheduling/mcp/dist/__tests__/portal-index-audit.test.d.ts +2 -0
- package/payload/platform/plugins/scheduling/mcp/dist/__tests__/portal-index-audit.test.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/__tests__/portal-index-audit.test.js +66 -0
- package/payload/platform/plugins/scheduling/mcp/dist/__tests__/portal-index-audit.test.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/portal-index-audit.d.ts +41 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/portal-index-audit.d.ts.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/portal-index-audit.js +75 -0
- package/payload/platform/plugins/scheduling/mcp/dist/lib/portal-index-audit.js.map +1 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.js +122 -0
- package/payload/platform/plugins/scheduling/mcp/dist/scripts/check-due-events.js.map +1 -1
- package/payload/server/public/activity.html +8 -6
- package/payload/server/public/assets/{AdminLoginScreens-DR5eLF-a.js → AdminLoginScreens-DkxQZnvB.js} +1 -1
- package/payload/server/public/assets/AdminShell-Cv_nIFGe.js +2 -0
- package/payload/server/public/assets/Checkbox-CsTWK8mm.js +1 -0
- package/payload/server/public/assets/activity-BbnTiVBT.js +1 -0
- package/payload/server/public/assets/{admin-D2KLZnQW.js → admin-BZY3i_Ff.js} +1 -1
- package/payload/server/public/assets/{browser-CDWqEiCD.js → browser-BbIiSFKr.js} +1 -1
- package/payload/server/public/assets/{calendar-BG7fOpbB.js → calendar-BvxeTHvQ.js} +1 -1
- package/payload/server/public/assets/chat-DUKxufRk.js +1 -0
- package/payload/server/public/assets/chevron-left-BtfJD6LL.js +1 -0
- package/payload/server/public/assets/data-hl1wa-Ax.js +1 -0
- package/payload/server/public/assets/{graph-DRloNic4.js → graph-CDSGRoeb.js} +1 -1
- package/payload/server/public/assets/graph-labels-C5qLwnWA.js +1 -0
- package/payload/server/public/assets/{maximize-2-CzDaBugs.js → maximize-2-CAzH8dED.js} +1 -1
- package/payload/server/public/assets/{operator-BZeeyait.js → operator-BK7r8DAB.js} +1 -1
- package/payload/server/public/assets/{page-ef-6rRPL.js → page-B5YngOrK.js} +1 -1
- package/payload/server/public/assets/{page-B0obcg3b.js → page-BsCS0Dmc.js} +1 -1
- package/payload/server/public/assets/{public-9D3MMOkC.js → public-C1Pz-IBs.js} +1 -1
- package/payload/server/public/assets/{rotate-ccw-DXEKUhXP.js → rotate-ccw-UDln4Tou.js} +1 -1
- package/payload/server/public/assets/{tasks-BB0L7e5a.js → tasks-B-cLsn3p.js} +1 -1
- package/payload/server/public/assets/{time-entry-format-CsYAjplS.js → time-entry-format-DPOBIE18.js} +1 -1
- package/payload/server/public/assets/{triangle-alert-0lSBIUg-.js → triangle-alert-Dz-CZKo5.js} +1 -1
- package/payload/server/public/assets/{useCopyFeedback-jTBQ2h0V.js → useCopyFeedback-wtUHGohk.js} +1 -1
- package/payload/server/public/assets/{useSelectionMode-BooArySZ.js → useSelectionMode-sph7AQT5.js} +1 -1
- package/payload/server/public/assets/useSubAccountSwitcher-BRIluIKf.css +1 -0
- package/payload/server/public/assets/{useVoiceRecorder-PUT8q_sm.js → useVoiceRecorder-DN4jYQ0A.js} +1 -1
- package/payload/server/public/brand-defaults.css +1 -0
- package/payload/server/public/browser.html +5 -5
- package/payload/server/public/calendar.html +6 -6
- package/payload/server/public/chat.html +12 -12
- package/payload/server/public/data.html +11 -11
- package/payload/server/public/graph.html +11 -11
- package/payload/server/public/index.html +14 -14
- package/payload/server/public/operator.html +14 -14
- package/payload/server/public/privacy.html +1 -0
- package/payload/server/public/public.html +12 -12
- package/payload/server/public/tasks.html +6 -5
- package/payload/server/public/vnc-popout.html +1 -0
- package/payload/server/server.js +741 -366
- package/payload/server/public/assets/AdminShell-D9zaUxPd.js +0 -2
- package/payload/server/public/assets/Checkbox-DcbbAIe5.js +0 -1
- package/payload/server/public/assets/activity-C9P5NjEZ.js +0 -1
- package/payload/server/public/assets/chat-RyH-WYQC.js +0 -1
- package/payload/server/public/assets/chevron-left-DmXCr6nB.js +0 -1
- package/payload/server/public/assets/data-BaY_LkLR.js +0 -1
- package/payload/server/public/assets/graph-labels-DD-GqS4v.js +0 -1
- package/payload/server/public/assets/useSubAccountSwitcher-D9knHOKq.css +0 -1
- /package/payload/server/public/assets/{useSubAccountSwitcher-BZnzc5C3.js → useSubAccountSwitcher-v8LyBzZN.js} +0 -0
package/payload/platform/docs/superpowers/plans/2026-07-20-task-1819-top-level-label-allowlist.md
ADDED
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
# Task 1819 — Top-Level Label Allowlist Implementation Plan
|
|
2
|
+
|
|
3
|
+
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
|
|
4
|
+
|
|
5
|
+
**Goal:** Make the two failing top-level-label tests pass by resolving the real disagreement between the derived allowlist and the client mirror, and register `CashEntry` as a top-level label across every registry that gates one.
|
|
6
|
+
|
|
7
|
+
**Architecture:** Two independent tasks. Task 1 is the 1819 correctness fix: one label into `STATIC_TOP_LEVEL_LABELS` plus the doc comment that would have prevented the drift. Task 2 registers `CashEntry` across six surfaces in the shared `graph-style` lib and the two UI label sets. A reviewer can accept Task 1 and reject Task 2.
|
|
8
|
+
|
|
9
|
+
**Tech Stack:** TypeScript, vitest, Node 22.22.0 via nvm.
|
|
10
|
+
|
|
11
|
+
## Global Constraints
|
|
12
|
+
|
|
13
|
+
- Run everything under Node 22.22.0 (`source ~/.nvm/nvm.sh && nvm use 22.22.0`). The repo's jsdom vitest env requires `require(esm)`, which needs Node >= 20.19 / >= 22.12.
|
|
14
|
+
- Working directory is the worktree: `/Users/neo/getmaxy/maxy-code/.claude/worktrees/task-1819-top-level-label-allowlist`. All paths below are relative to it.
|
|
15
|
+
- Never edit or rebuild through `maxy-code/platform/lib/graph-style/dist` while it is a symlink to the parent checkout. Task 2 Step 1 replaces it with a local build.
|
|
16
|
+
- Do not edit either test's assertions. The tests are correct; the sets are wrong.
|
|
17
|
+
- Every commit carries the trailers:
|
|
18
|
+
```
|
|
19
|
+
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
|
20
|
+
Session: 693bcfd0-f04e-49ed-8ebe-593e59be24c2
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
### Task 1: Add `InboundInvoice` to the static allowlist
|
|
26
|
+
|
|
27
|
+
`InboundInvoice` is a genuine operator-entry top-level label. Commit `7b225f814` moved its row from `schema-construction.md`'s parsed `## Top-level node types` table into `schema-base.md`'s `## Node Types` table, which the derivation deliberately never parses because it mixes in child types. `STATIC_TOP_LEVEL_LABELS` is the compartment for exactly that case.
|
|
28
|
+
|
|
29
|
+
**Files:**
|
|
30
|
+
- Modify: `maxy-code/platform/ui/server/lib/top-level-labels.ts:25-69`
|
|
31
|
+
- Test (existing, do not edit): `maxy-code/platform/ui/server/lib/top-level-labels.test.ts`
|
|
32
|
+
- Test (existing, do not edit): `maxy-code/platform/ui/server/routes/__tests__/graph-default-topLevel.test.ts`
|
|
33
|
+
|
|
34
|
+
**Interfaces:**
|
|
35
|
+
- Consumes: nothing from other tasks.
|
|
36
|
+
- Produces: `STATIC_TOP_LEVEL_LABELS` gains the member `'InboundInvoice'`. Task 2 adds `'CashEntry'` to this same set.
|
|
37
|
+
|
|
38
|
+
- [ ] **Step 1: Run the two tests to confirm they fail**
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
cd maxy-code/platform/ui
|
|
42
|
+
source ~/.nvm/nvm.sh && nvm use 22.22.0
|
|
43
|
+
npx vitest run server/lib/top-level-labels.test.ts server/routes/__tests__/graph-default-topLevel.test.ts
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Expected: `Test Files 2 failed (2)`, `Tests 2 failed | 12 passed (14)`. Both failures are the same set diff, with `InboundInvoice` present in expected and absent from received.
|
|
47
|
+
|
|
48
|
+
- [ ] **Step 2: Add the label**
|
|
49
|
+
|
|
50
|
+
In `maxy-code/platform/ui/server/lib/top-level-labels.ts`, inside `STATIC_TOP_LEVEL_LABELS`, add `'InboundInvoice'` immediately after `'Invoice',` (line 51) so the two invoice labels read together:
|
|
51
|
+
|
|
52
|
+
```ts
|
|
53
|
+
'Invoice',
|
|
54
|
+
// Supplier invoice. Declared in schema-base.md's `## Node Types` table
|
|
55
|
+
// (promoted there from schema-construction.md's top-level table by
|
|
56
|
+
// 7b225f814), which this module never parses — so it is static, not
|
|
57
|
+
// derived. Top-level because it is operator-entry with a natural key
|
|
58
|
+
// (accountId, supplier, confirmationNumber), unlike its InvoiceLine /
|
|
59
|
+
// InvoicePayment / Credit children.
|
|
60
|
+
'InboundInvoice',
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
- [ ] **Step 3: Document the reverse migration**
|
|
64
|
+
|
|
65
|
+
The existing doc comment on `STATIC_TOP_LEVEL_LABELS` covers only the forward direction. Replace the comment at lines 25-29 with:
|
|
66
|
+
|
|
67
|
+
```ts
|
|
68
|
+
/**
|
|
69
|
+
* Top-level labels not (yet) sourced from a vertical `## Top-level node types`
|
|
70
|
+
* section. Membership moves in both directions, and both are load-bearing:
|
|
71
|
+
*
|
|
72
|
+
* - A vertical GAINS a top-level section: its labels move from here into
|
|
73
|
+
* the derived union, and the STATIC copy is removed in the same edit.
|
|
74
|
+
* - A label is PROMOTED INTO `schema-base.md`: it must be ADDED here in the
|
|
75
|
+
* same edit. `schema-base.md` has no top-level section and is never
|
|
76
|
+
* parsed (its `## Node Types` table mixes in child types), so a promotion
|
|
77
|
+
* silently deletes the label from the derived set. This is what happened
|
|
78
|
+
* to `InboundInvoice` in 7b225f814 and it is what Task 1819 fixed.
|
|
79
|
+
*/
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
- [ ] **Step 4: Run the two tests to verify they pass**
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
cd maxy-code/platform/ui
|
|
86
|
+
source ~/.nvm/nvm.sh && nvm use 22.22.0
|
|
87
|
+
npx vitest run server/lib/top-level-labels.test.ts server/routes/__tests__/graph-default-topLevel.test.ts
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Expected: `Test Files 2 passed (2)`, `Tests 14 passed (14)`.
|
|
91
|
+
|
|
92
|
+
The `keeps STATIC_TOP_LEVEL_LABELS disjoint from the table-derived labels` test in the same file must still pass — it proves `InboundInvoice` is genuinely absent from every parsed table, confirming static is the right home.
|
|
93
|
+
|
|
94
|
+
- [ ] **Step 5: Commit**
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
git add maxy-code/platform/ui/server/lib/top-level-labels.ts
|
|
98
|
+
git commit -m "fix: restore InboundInvoice to the top-level label allowlist (1819)
|
|
99
|
+
|
|
100
|
+
Commit 7b225f814 promoted the InboundInvoice row out of
|
|
101
|
+
schema-construction.md's parsed top-level table into schema-base.md's
|
|
102
|
+
Node Types table. That table is never parsed — it mixes child types —
|
|
103
|
+
so the derived allowlist silently lost a real operator-entry label and
|
|
104
|
+
the deep-equals guard against the client mirror went red.
|
|
105
|
+
|
|
106
|
+
The client mirror was right. STATIC_TOP_LEVEL_LABELS is the compartment
|
|
107
|
+
for base-schema labels with no top-level section, and InboundInvoice had
|
|
108
|
+
never been added to it.
|
|
109
|
+
|
|
110
|
+
Also documents the reverse migration on STATIC_TOP_LEVEL_LABELS. The
|
|
111
|
+
comment covered only 'vertical gains a section, label leaves static' and
|
|
112
|
+
was silent on 'label promoted into base, label enters static' — the
|
|
113
|
+
direction that caused this.
|
|
114
|
+
|
|
115
|
+
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
|
116
|
+
Session: 693bcfd0-f04e-49ed-8ebe-593e59be24c2"
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
### Task 2: Register `CashEntry` as a top-level label
|
|
122
|
+
|
|
123
|
+
`CashEntry` was added by the same commit and is absent from every registry, so it fails no test but has no `/graph` chip. It is money "not attached to any invoice" with no parent label, so unlike a child label it cannot be reached by drilling down — without a chip it is unreachable except by search.
|
|
124
|
+
|
|
125
|
+
**Files:**
|
|
126
|
+
- Modify: `maxy-code/platform/lib/graph-style/src/index.ts` — colour table, icon table, `pickShortLabel`, `pickDisplayName`
|
|
127
|
+
- Modify: `maxy-code/platform/ui/app/lib/graph-labels.ts:139-191` — `FILTER_TOP_LEVEL_LABELS`
|
|
128
|
+
- Modify: `maxy-code/platform/ui/server/lib/top-level-labels.ts` — `STATIC_TOP_LEVEL_LABELS`
|
|
129
|
+
- Test (existing): `maxy-code/platform/lib/graph-style/src/__tests__/icons.test.ts`, `parity.test.ts`
|
|
130
|
+
- Test (existing): `maxy-code/platform/ui/app/lib/__tests__/graph-labels.test.ts`
|
|
131
|
+
|
|
132
|
+
**Interfaces:**
|
|
133
|
+
- Consumes: `STATIC_TOP_LEVEL_LABELS` from Task 1.
|
|
134
|
+
- Produces: `GRAPH_LABEL_COLOURS.CashEntry === '#7D5A2B'`; `iconForLabel('CashEntry')` returns a non-null SVG string; `CashEntry` is a member of both `FILTER_TOP_LEVEL_LABELS` and `STATIC_TOP_LEVEL_LABELS`.
|
|
135
|
+
|
|
136
|
+
- [ ] **Step 1: Replace the dist symlink with a local build**
|
|
137
|
+
|
|
138
|
+
`dist` currently points at the parent checkout. Building through it would write to the shared checkout other sessions use.
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
cd /Users/neo/getmaxy/maxy-code/.claude/worktrees/task-1819-top-level-label-allowlist
|
|
142
|
+
ls -ld maxy-code/platform/lib/graph-style/dist # confirm it is a symlink (leading 'l')
|
|
143
|
+
rm -f maxy-code/platform/lib/graph-style/dist
|
|
144
|
+
source ~/.nvm/nvm.sh && nvm use 22.22.0
|
|
145
|
+
cd maxy-code/platform
|
|
146
|
+
./ui/node_modules/.bin/tsc -p lib/graph-style/tsconfig.json
|
|
147
|
+
ls -ld lib/graph-style/dist # now a real directory ('d')
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Expected: `tsc` exits 0 and `dist` is a real directory. Use `ui/node_modules/.bin/tsc` explicitly — the libs have no `package.json`, so a bare `npx tsc` resolves to an unrelated package.
|
|
151
|
+
|
|
152
|
+
- [ ] **Step 2: Write the failing test**
|
|
153
|
+
|
|
154
|
+
Add to `maxy-code/platform/lib/graph-style/src/__tests__/parity.test.ts`, inside the `palette invariants` describe block:
|
|
155
|
+
|
|
156
|
+
```ts
|
|
157
|
+
it("registers CashEntry as its own hue, distinct from the invoice labels", () => {
|
|
158
|
+
expect(GRAPH_LABEL_COLOURS.CashEntry).toBe("#7D5A2B");
|
|
159
|
+
expect(GRAPH_LABEL_COLOURS.CashEntry).not.toBe(GRAPH_LABEL_COLOURS.Invoice);
|
|
160
|
+
expect(GRAPH_LABEL_COLOURS.CashEntry).not.toBe(GRAPH_LABEL_COLOURS.InboundInvoice);
|
|
161
|
+
});
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
- [ ] **Step 3: Run it to verify it fails**
|
|
165
|
+
|
|
166
|
+
```bash
|
|
167
|
+
cd maxy-code/platform/lib/graph-style
|
|
168
|
+
source ~/.nvm/nvm.sh && nvm use 22.22.0
|
|
169
|
+
../../ui/node_modules/.bin/vitest run
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
Expected: FAIL on the new test with `expected undefined to be '#7D5A2B'`. The `icons.test.ts` coverage test still passes at this point, because `CashEntry` is not yet in the colour table.
|
|
173
|
+
|
|
174
|
+
- [ ] **Step 4: Add the colour**
|
|
175
|
+
|
|
176
|
+
In `maxy-code/platform/lib/graph-style/src/index.ts`, append to the END of the `GRAPH_LABEL_COLOURS` object, after `Hypothesis: '#9A8C3E',` (line 147):
|
|
177
|
+
|
|
178
|
+
```ts
|
|
179
|
+
|
|
180
|
+
// Ledger cash movement (schema-base.md, added by 7b225f814). One movement
|
|
181
|
+
// of money attached to no invoice — operator-entry with no parent to drill
|
|
182
|
+
// down from, so it is a top-level chip. Burnished olive-gold sits in the
|
|
183
|
+
// money register beside Invoice's brown without colliding with it.
|
|
184
|
+
//
|
|
185
|
+
// Deliberately appended at the END rather than beside the ledger family:
|
|
186
|
+
// SHAPE_BY_LABEL assigns shapes by index position in ALL_GRAPH_LABELS
|
|
187
|
+
// (this object's key order), so a mid-table insert would silently change
|
|
188
|
+
// the rendered shape of every label after it.
|
|
189
|
+
CashEntry: '#7D5A2B',
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
- [ ] **Step 5: Run the tests to see the icon gate fail**
|
|
193
|
+
|
|
194
|
+
```bash
|
|
195
|
+
cd maxy-code/platform/lib/graph-style
|
|
196
|
+
source ~/.nvm/nvm.sh && nvm use 22.22.0
|
|
197
|
+
../../ui/node_modules/.bin/vitest run
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
Expected: the new palette test now PASSES, and `icons.test.ts` now FAILS with `CashEntry` listed in the missing-glyph array. This is the coverage gate doing its job.
|
|
201
|
+
|
|
202
|
+
- [ ] **Step 6: Add the icon**
|
|
203
|
+
|
|
204
|
+
In the same file, append to the END of the `LABEL_ICONS` object (the Lucide `banknote` glyph):
|
|
205
|
+
|
|
206
|
+
```ts
|
|
207
|
+
CashEntry: '<rect width="20" height="12" x="2" y="6" rx="2"></rect><circle cx="12" cy="12" r="2"></circle><path d="M6 12h.01"></path><path d="M18 12h.01"></path>',
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
- [ ] **Step 7: Add the caption branches**
|
|
211
|
+
|
|
212
|
+
`CashEntry`'s properties are `accountId`, `entryId`, `direction`, `amount`, `date`, `description`. The generic caption fallthrough only checks `name`, `title`, `summary`, `givenName`, `subject`, `text`, so without a branch every node renders as the literal string `CashEntry`. Both caption functions carry per-label branches and both need one.
|
|
213
|
+
|
|
214
|
+
In `pickShortLabel`, after the `WhatsAppGroup` branch and before the `Message` branch:
|
|
215
|
+
|
|
216
|
+
```ts
|
|
217
|
+
} else if (primaryLabel === 'CashEntry') {
|
|
218
|
+
const desc = typeof props.description === 'string' ? props.description : ''
|
|
219
|
+
if (desc.length > 0) {
|
|
220
|
+
return desc.length > 24 ? desc.slice(0, 24) + '…' : desc
|
|
221
|
+
}
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
In `pickDisplayName`, add the matching untruncated branch in the same relative position:
|
|
225
|
+
|
|
226
|
+
```ts
|
|
227
|
+
} else if (primaryLabel === 'CashEntry') {
|
|
228
|
+
const desc = typeof props.description === 'string' ? props.description : ''
|
|
229
|
+
if (desc.length > 0) return desc
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
- [ ] **Step 8: Run the graph-style suite to verify it passes**
|
|
233
|
+
|
|
234
|
+
```bash
|
|
235
|
+
cd maxy-code/platform/lib/graph-style
|
|
236
|
+
source ~/.nvm/nvm.sh && nvm use 22.22.0
|
|
237
|
+
../../ui/node_modules/.bin/vitest run
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
Expected: all tests pass, including the icon-coverage test and the hex-format invariant.
|
|
241
|
+
|
|
242
|
+
- [ ] **Step 9: Rebuild dist so the UI sees the new symbols**
|
|
243
|
+
|
|
244
|
+
```bash
|
|
245
|
+
cd maxy-code/platform
|
|
246
|
+
source ~/.nvm/nvm.sh && nvm use 22.22.0
|
|
247
|
+
./ui/node_modules/.bin/tsc -p lib/graph-style/tsconfig.json
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
Expected: exit 0.
|
|
251
|
+
|
|
252
|
+
- [ ] **Step 10: Add `CashEntry` to both label sets**
|
|
253
|
+
|
|
254
|
+
In `maxy-code/platform/ui/app/lib/graph-labels.ts`, inside `FILTER_TOP_LEVEL_LABELS`, after `'InboundInvoice',` (line 166):
|
|
255
|
+
|
|
256
|
+
```ts
|
|
257
|
+
'CashEntry',
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
In `maxy-code/platform/ui/server/lib/top-level-labels.ts`, inside `STATIC_TOP_LEVEL_LABELS`, after the `'InboundInvoice',` entry added in Task 1:
|
|
261
|
+
|
|
262
|
+
```ts
|
|
263
|
+
// Ledger cash movement, declared in schema-base.md. Operator-entry with
|
|
264
|
+
// a natural key (accountId, entryId) and no parent label, so it is
|
|
265
|
+
// reachable only as a chip.
|
|
266
|
+
'CashEntry',
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
Both sets must change together — the deep-equals test from Task 1 fails if only one does. That failure is the guard working.
|
|
270
|
+
|
|
271
|
+
- [ ] **Step 11: Run the full UI graph-label surface**
|
|
272
|
+
|
|
273
|
+
```bash
|
|
274
|
+
cd maxy-code/platform/ui
|
|
275
|
+
source ~/.nvm/nvm.sh && nvm use 22.22.0
|
|
276
|
+
npx vitest run server/lib/top-level-labels.test.ts \
|
|
277
|
+
server/routes/__tests__/graph-default-topLevel.test.ts \
|
|
278
|
+
app/lib/__tests__/graph-labels.test.ts \
|
|
279
|
+
app/data/__tests__/dynamic-chips.test.ts
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
Expected: all four files pass. The hex-duplicate-rejection test in `graph-labels.test.ts` is the one that proves `#7D5A2B` collides with nothing.
|
|
283
|
+
|
|
284
|
+
- [ ] **Step 12: Commit**
|
|
285
|
+
|
|
286
|
+
```bash
|
|
287
|
+
git add maxy-code/platform/lib/graph-style/src/index.ts \
|
|
288
|
+
maxy-code/platform/lib/graph-style/src/__tests__/parity.test.ts \
|
|
289
|
+
maxy-code/platform/ui/app/lib/graph-labels.ts \
|
|
290
|
+
maxy-code/platform/ui/server/lib/top-level-labels.ts
|
|
291
|
+
git commit -m "feat(graph): register CashEntry as a top-level label
|
|
292
|
+
|
|
293
|
+
CashEntry arrived in schema-base.md with 7b225f814 and was registered
|
|
294
|
+
nowhere, so /graph offered no chip for it. It is money attached to no
|
|
295
|
+
invoice and has no parent label, so unlike a child label it cannot be
|
|
296
|
+
reached by drilldown — without a chip it is unreachable except by search.
|
|
297
|
+
|
|
298
|
+
Six surfaces: colour, icon, both caption functions, the client chip
|
|
299
|
+
mirror, and the server static allowlist.
|
|
300
|
+
|
|
301
|
+
The colour is appended at the end of GRAPH_LABEL_COLOURS rather than
|
|
302
|
+
beside the ledger family on purpose. SHAPE_BY_LABEL assigns shapes by
|
|
303
|
+
index position in that object's key order, so a mid-table insert would
|
|
304
|
+
have silently changed the rendered shape of ~40 other labels.
|
|
305
|
+
|
|
306
|
+
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
|
307
|
+
Session: 693bcfd0-f04e-49ed-8ebe-593e59be24c2"
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
---
|
|
311
|
+
|
|
312
|
+
## Verification (after both tasks)
|
|
313
|
+
|
|
314
|
+
```bash
|
|
315
|
+
cd maxy-code/platform/ui
|
|
316
|
+
source ~/.nvm/nvm.sh && nvm use 22.22.0
|
|
317
|
+
npx tsc --noEmit
|
|
318
|
+
npx vitest run
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
Expected: `tsc` exits 0. The full suite has no failures attributable to these files. Compare any residual red against the parent checkout on `main` before treating it as caused by this diff.
|