From 58154ca771142b53e2c8e7c78ddd7ecc96a36eb0 Mon Sep 17 00:00:00 2001 From: Amr Elsayed Date: Fri, 14 Aug 2026 10:27:27 +1000 Subject: [PATCH 1/7] chore(porch): 1444 init air --- .../status.yaml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 codev/projects/1444-stream-deck-re-glyph-the-catch/status.yaml diff --git a/codev/projects/1444-stream-deck-re-glyph-the-catch/status.yaml b/codev/projects/1444-stream-deck-re-glyph-the-catch/status.yaml new file mode 100644 index 000000000..6a6e0511b --- /dev/null +++ b/codev/projects/1444-stream-deck-re-glyph-the-catch/status.yaml @@ -0,0 +1,14 @@ +id: '1444' +title: stream-deck-re-glyph-the-catch +protocol: air +phase: implement +plan_phases: [] +current_plan_phase: null +gates: + pr: + status: pending +iteration: 1 +build_complete: false +history: [] +started_at: '2026-08-14T00:27:27.654Z' +updated_at: '2026-08-14T00:27:27.655Z' From 36d5cf85581ea011024140a1aa7088d7267a426a Mon Sep 17 00:00:00 2001 From: Amr Elsayed Date: Fri, 14 Aug 2026 10:54:26 +1000 Subject: [PATCH 2/7] [Air #1444] feat: re-glyph catch-all Codev Action off the terminal picture The catch-all Codev Action drew a terminal glyph (icons/action.*). #1440 gave the new open-terminal action its own terminal-glyph icon, so the two read near-identical in the Stream Deck action picker. Re-glyph the catch-all onto the Codev brand mark (icons/plugin.svg): a generic Codev action wearing the Codev mark reads correctly and the terminal picture stays with the action that opens a terminal. Extends scripts/render-action-icons.mjs (from #1440) with a brand-mark source that flows through the same trim -> fit -> composite pipeline as the glyphs; no new artwork, no dependency. Manifest references are unchanged (icons/list/action, icons/action) - only the pixels behind those filenames are regenerated. CodevAction has no runtime composite face, so this fixes both the picker list icon and the physical key face. --- .../icons/action.png | Bin 1160 -> 2920 bytes .../icons/action@2x.png | Bin 2266 -> 7173 bytes .../icons/list/action.png | Bin 439 -> 617 bytes .../icons/list/action@2x.png | Bin 855 -> 1099 bytes .../scripts/render-action-icons.mjs | 82 ++++++++++++++---- .../src/__tests__/manifest-icons.test.ts | 39 +++++++++ .../src/__tests__/render-action-icons.test.ts | 38 +++++++- codev/state/air-1444_thread.md | 29 +++++++ 8 files changed, 171 insertions(+), 17 deletions(-) create mode 100644 codev/state/air-1444_thread.md diff --git a/apps/streamdeck/com.cluesmith.codev.sdPlugin/icons/action.png b/apps/streamdeck/com.cluesmith.codev.sdPlugin/icons/action.png index 617c8a270d718b6328c5fce0cc2024cc5605fd58..a42e03bcab229b87f57a893582f733b9f5864877 100644 GIT binary patch literal 2920 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 literal 2266 zcma);c{me}8^D>#Fibfj$K2->$x&;~ni*oqkzIoBhA-OMXW@YrNu0tNbs*( z@NcJS@$=@;Fd11-w3~h^3)mBFmv z{vIf}v)Oh4$@Z0!hLlQKa-aLTOswrzEBpX^LM4Kgc3ea(#d zN*-v7IqZXF@LJmR_!sO(t5ROBoo}5Xt37PEKQZ-^TIQ~pV}Di@0#x+jm#+N_X4dvj zxs80WZ{}xm*;1DBmD|SZ3_%mtX?|(HT!kN3hQB4ZM&lWX<8_wUA-)@(S{Y*X#NRHF z4>qG^AVhCly`tlC7$h|T*Z`|XeAU0QmY;6+SK?(Aen*y@jN=``yTTi&dycY8LZn+e*g=;EI z5so>RTq&pI+L^KN;=?x;i;k3QzWA(WgSb;Aa?7>YKyTt8xmJJ4o;l}TnLmLIhFta& z6f1NwDs}CoU`#H4B2aEWUyKBaj#*J3{iv7C=V>XbPITRB@#nS~Ew!0lsJTwSAI4&L zqZn$u11O1Z-#yqGI8%ZKj7GhJ=Q4c}-r|DYv|=3ak@>7Itv@3J3fTbSJerh;WP)1n z_9<2LqvoX|Od;8G=GXm?hHWf2zX zYn{s~aoU3k;|9asmK|m&xrF_iKdwr)m8~ z69Ow1PBP-F{L!IX2^J|2{5s+nBro%74l1w`{or&GapzRfh*z?@=20!18e{Z)MbR@FQ6+8jzI2a3V@UVKruFri z7TJs5<=mHf4-2=m3tJnDbRC*Xj%q;$kAwgoTncqBd(#(wRM)Y1kRz{tmi|qDc5mSm zSH{XA&uS!GGGeuV#qYPrmC)F9H^V~*fzO@a8wd^Xi|8V-#=O(qekBb7C~EkcNZLK? zs546u^2+0TUTsL9rgnM(r)|G(ZcwR(bB_V)+ECIt=1v?54@sF7S&y@TCOAC{&U0H~ zXO<_%SwoM%4X0NckRKs^$}-y>o}0u0L-L?!YW(klKwV?LhKagrQ*L92WAp7(0W|mXg=90R zbwNn&|w5{oVUsarmzTvp5Z3DRU`db|z z5}5|u!WWX_dwOXppW4^2=%!W3;7Jh7@FET#zz^Zhvlo4q$BRxf?lswxFZ7@Xrj>H1=oq4?8J1#*{GjR?9O zp|7C_(4Ch`_(Isp-B=Fj#T6o4d0_LjBv2&ezjg5CkAthZK>^$iKuxuGWb`bw78G}e7967kJ~(g49UzL}orTF_Gd*e)LeO9nNo|F)AixA^NemGO(Wt5jU-%Lx10K?d z(tqCMR;yPr8m=g9cO5LM>JP3v^OzZ7N#-8=2=SuE*FG&Geil{#s0Srq*JsC&ZDvV$ zjdFwv$wufDG7D=5Tm3;3QF=xIWU08VH9_CZ*KR$+JW1 z(p0h0a|9Tj*^O9JH!WpSao7pL^iCCFr$+_og8R{QQJm@(@rITeY9@VYGTDc0Hg?;y z5#BT}F$i#YXWyK&l3}N6ZYLR}NHr!j3iTb|nN0-a&d=w>!KDVO^dIiZ|DbB-pR>ll QJ@{F;%uTJ)G?ZuTKcd1N#{d8T diff --git a/apps/streamdeck/com.cluesmith.codev.sdPlugin/icons/list/action.png b/apps/streamdeck/com.cluesmith.codev.sdPlugin/icons/list/action.png index 771443dccc963a613235de857f98193814197145..eb73006f5a20fee66488396d7b8b9cd90954e636 100644 GIT binary patch literal 617 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc0wmQNuC@Uwg=CK)Uj~LMH3o);76yi2K%s^g z3=E|P3=FRl7#OT(FffQ0%-I!a1C(G&@^*J&U|7|wYy{-7mw5WRvcKZsV=$JrIk`NZ zfq~K2)5S4F?^s&fym)#>1QTAOA(;o_NRna3{sOj@&a>hYfw;%9QW9Gh%&Dn%^l zY($)T<Ap9ckPvZR+2S~<+yCfw)m5bw{5N$of9i9zqQW0&G+}p=#ze_Yj!Ry2=qOy7d(yI z_10;A>CZv^dg5;azTWKEm7aDjI7I7K?0P}b={2RNopoiydb0jZtx73BmuC3Yq}aN7 z=gg%(PiuB<`Z?3A!|(W6RFy6>&XWtd%BTNJULvwZEWkAL|e?7xtI=lPTc=Kd^F zz_3;=ag8WRNi0dVN-jzTQVd20MrOJO7P^KeAqECkriNBVmfApufkAGu@7Ik(oJCu^MiAM#q~m2b!kq_BmZ$ zRb5xKU|T?pF0dp|TJ437LQ}aap2aD)8(^iQ-e*bUqCtwpynk!^gS+D}xT(<;4_ATr zz#h;C;tJy#o&|RVYyo$GtCBvI7(C3=?w=uk+sS

kDa*Ye%LoRht*ni)je%5a=cM zM60Q;aAfOIE50!nUM6eG7Va<>yLupZC}swSq2_UdTBfMJqI>2Ng)ykJOO_E zO|WF`9q?4r+t#y+xZbJ+dvz7G1tUwBCA|Xfw#p{5IF_^%aje5&`(|?07A%J2iZG}J zn8erQ4%^M)3UJWz={0%XO<*0kCh6n3H3!YnzP@Df{~>N)1^>0dwm!`L3-|?C;7rHD SQ2#{$0000k+ z0|T?Zr;B5V$MLsUVl%F#N*w=~y*5!Rm0Pp)X`|ST&1;i{Pv41Pv$}j{y6My-*BTcD zD9)^0@T^gFo3LV$YF1ka`{g)+IX{eEq;71!gfiv+oHc+ z>$A+2c|{K0?OW>e_1)I{sl3-JPE9^`ngb zURm|Wqfawz$71ev++XUZE}OAFq}NL|?&6%r)y5|S*Iv`w8os&6y!qw5)j@4Z$5r=a z&B*H2+B5WH)x38XhYkDm%f^C&!t5{Z*-7n09)TK+g7yraIpic6-?@*wJ77*7)N@v)dVy zf`2$RGVk+vcia9@>0!R_TkX#ZEtCGfzK~h!Lj9`!jJneeZ9-#bcmi{iYKdz^NlIc# zs#S7PDv)9@GB7gJHL%b%Gzl>8^7c_tjWah+x3FsIohK6n4y(q^;ef6m%H(#$)^^Z|#=UPx6zAwC80C%o9PwOFvHnI0WFCq<_6GzP+UaUBEDaYXDYz5_bU@ zm2|{KR$3;|F+*|)z-a&-Zm_EWJd!kQMO2o^+?{&9jQ}_d;G_H39DwtZ`dnn;TeQXG zk5aBVf1~c3ZA~`1W?R)l1$wTX0x*&gc7fzW-^!eWB*X7l0Pf{^oyhBh7hT+x7l&<&21q{fD!0g)d)w6BG~qc0 zeHp;nqKagjpH18-fL%cx8;#n;?#S8a_B_jF(+GNm&H$JOFyT2j9gAaq>7(C2?!LLf zr!YCi@+m%-XC=y$gGT%YKz}5f$&Tq83X)F&^nc~(*ZQ$s#zF+9h1{Z3$-CXs@3vXf z$1J`qfw9qsq_0GtRjb0p9&s`G9Ylop@3_B?EP!!Y0+YKcoo^ zBYFVfq(^LzqjVK{w>&x>?o{ zU__jQB)_;8Wqn=f@y`+CDj(y{)e~#T`|-%8d<)9O1j%nn?*I4m+kf!^a|O!@zW~#* V8V2}Rg7*Lb002ovPDHLkV1l9En~eYf diff --git a/apps/streamdeck/scripts/render-action-icons.mjs b/apps/streamdeck/scripts/render-action-icons.mjs index ae839707a..365c370dd 100644 --- a/apps/streamdeck/scripts/render-action-icons.mjs +++ b/apps/streamdeck/scripts/render-action-icons.mjs @@ -1,10 +1,18 @@ -// Render the dedicated manifest action icons for `send-queue` and `open-terminal` (#1440). +// Render the dedicated manifest action icons for `send-queue`, `open-terminal` (#1440) and the +// catch-all `action` (#1444). // // SINGLE SOURCE: the glyph vectors are NOT re-drawn here — they are parsed out of // `src/face.ts`'s GLYPHS map, the same vectors the runtime key face draws via // `labelFaceSvg('comment'|'terminal', …)`. So the action-picker icon and the live hardware key // agree by construction; changing a glyph in face.ts and re-running this script keeps them aligned. // +// BRAND-SOURCED: the `action` icon is the exception — it renders from the plugin's own brand mark +// (`icons/plugin.svg`), not a face.ts glyph. `Codev Action` is a configurable catch-all that runs +// any verb, so #1440's terminal glyph both mislabeled it and collided with the new open-terminal +// icon; the Codev mark reads as "a generic Codev action" and needs no new artwork (#1444). The mark +// is already monochrome white on the same viewBox we reuse, so it flows through the identical +// trim → fit → composite pipeline as the glyphs. +// // FIT: the glyphs don't fill their authored 24×24 box (comment ≈ 18×17, terminal ≈ 20×16), and a // transparent list icon needs far less padding than a rounded-key image. So we render the glyph, // trim it to its true drawn bounding box, then scale that bbox to the SAME fill fraction the @@ -26,6 +34,7 @@ import { tmpdir } from 'node:os'; const HERE = dirname(fileURLToPath(import.meta.url)); const PLUGIN = join(HERE, '..', 'com.cluesmith.codev.sdPlugin'); const FACE_TS = join(HERE, '..', 'src', 'face.ts'); +const BRAND_SVG = join(PLUGIN, 'icons', 'plugin.svg'); // name → the GLYPHS key in face.ts it renders from. export const ICONS = [ @@ -33,6 +42,9 @@ export const ICONS = [ { name: 'open-terminal', glyph: 'terminal' }, ]; +// name → rendered from the brand mark in icons/plugin.svg instead of a face.ts glyph (#1444). +export const BRAND_ICONS = [{ name: 'action' }]; + const GLYPH_COLOR = '#ffffff'; const BG = '#1C2128'; // rounded-key ground, matching icons/action.png & siblings const CORNER_RADIUS = 12; // measured from the existing 72px key images (scales with size) @@ -72,6 +84,25 @@ function glyphSvg(inner) { return `${inner}`; } +/** + * Pull the brand mark out of icons/plugin.svg: its single `` group (the white handshake path) + * and the SVG's viewBox. The opaque background `` is left behind, so the mark renders + * transparent — the same raster shape renderKey/renderList expect. Throws loudly if the mark's + * shape drifts, so a silent stale-icon build can't happen. Returns the group already white; unlike + * the glyphs it carries no `${c}` placeholder, so no recolor step is needed. + */ +export function extractBrandMark(svgSrc) { + const viewBox = svgSrc.match(/viewBox="([^"]*)"/); + const group = svgSrc.match(/]*>[\s\S]*?<\/g>/); + if (!viewBox || !group) throw new Error('brand mark: expected with a group in plugin.svg'); + return { viewBox: viewBox[1], inner: group[0] }; +} + +/** The brand mark on its own, high-res, transparent — same role as glyphSvg for the glyphs. */ +function brandSvg({ viewBox, inner }) { + return `${inner}`; +} + function tmp(tag) { return join(tmpdir(), `sd-icon-1440-${tag}`); } @@ -126,6 +157,34 @@ function assertListCoverage(out, size, min) { } } +/** + * The four manifest variants a single high-res transparent source raster produces: the 72/144 key + * faces (glyph over the rounded ground) and the 20/40 transparent list icons. Shared by the glyph- + * and brand-sourced icons so both fit and center identically. + */ +function emit(name, srcPng) { + renderKey(srcPng, join(PLUGIN, 'icons', `${name}.png`), 72); + renderKey(srcPng, join(PLUGIN, 'icons', `${name}@2x.png`), 144); + renderList(srcPng, join(PLUGIN, 'icons', 'list', `${name}.png`), 20); + renderList(srcPng, join(PLUGIN, 'icons', 'list', `${name}@2x.png`), 40); + assertListCoverage(join(PLUGIN, 'icons', 'list', `${name}@2x.png`), 40, 0.8); +} + +/** Rasterize a source SVG to the shared high-res transparent raster, run `emit`, then clean up. */ +function build(name, svg, tag, label) { + const svgFile = tmp(`${tag}.svg`); + const srcPng = tmp(`${tag}.png`); + writeFileSync(svgFile, svg); + execFileSync('rsvg-convert', ['-w', String(RENDER_PX), '-h', String(RENDER_PX), svgFile, '-o', srcPng]); + try { + emit(name, srcPng); + } finally { + rmSync(svgFile, { force: true }); + rmSync(srcPng, { force: true }); + } + console.log(`rendered ${name} (${label}) → 72/144/20/40`); +} + function main() { ensureTool('rsvg-convert', 'brew install librsvg'); ensureTool('magick', 'brew install imagemagick'); @@ -134,21 +193,12 @@ function main() { mkdirSync(join(PLUGIN, 'icons', 'list'), { recursive: true }); for (const { name, glyph } of ICONS) { - const svgFile = tmp(`${glyph}.svg`); - const glyphPng = tmp(`${glyph}.png`); - writeFileSync(svgFile, glyphSvg(extractGlyph(faceSrc, glyph, GLYPH_COLOR))); - execFileSync('rsvg-convert', ['-w', String(RENDER_PX), '-h', String(RENDER_PX), svgFile, '-o', glyphPng]); - try { - renderKey(glyphPng, join(PLUGIN, 'icons', `${name}.png`), 72); - renderKey(glyphPng, join(PLUGIN, 'icons', `${name}@2x.png`), 144); - renderList(glyphPng, join(PLUGIN, 'icons', 'list', `${name}.png`), 20); - renderList(glyphPng, join(PLUGIN, 'icons', 'list', `${name}@2x.png`), 40); - assertListCoverage(join(PLUGIN, 'icons', 'list', `${name}@2x.png`), 40, 0.8); - } finally { - rmSync(svgFile, { force: true }); - rmSync(glyphPng, { force: true }); - } - console.log(`rendered ${name} (from GLYPHS.${glyph}) → 72/144/20/40`); + build(name, glyphSvg(extractGlyph(faceSrc, glyph, GLYPH_COLOR)), glyph, `from GLYPHS.${glyph}`); + } + + const brandSrc = readFileSync(BRAND_SVG, 'utf8'); + for (const { name } of BRAND_ICONS) { + build(name, brandSvg(extractBrandMark(brandSrc)), 'brand', 'from icons/plugin.svg brand mark'); } } diff --git a/apps/streamdeck/src/__tests__/manifest-icons.test.ts b/apps/streamdeck/src/__tests__/manifest-icons.test.ts index 6df2abeca..082bebe75 100644 --- a/apps/streamdeck/src/__tests__/manifest-icons.test.ts +++ b/apps/streamdeck/src/__tests__/manifest-icons.test.ts @@ -96,3 +96,42 @@ describe('#1440 dedicated action icons', () => { expect(pngSize(join(pluginDir, `icons/list/${name}@2x.png`))).toEqual({ w: 40, h: 40 }); }); }); + +/** + * #1444: the catch-all `Codev Action` was re-glyphed off the terminal picture (which now belongs to + * the dedicated open-terminal action from #1440) onto the Codev brand mark. Its manifest references + * are unchanged — only the pixels behind `icons/action` were regenerated — so these guards pin both + * the still-shared filenames and the fix itself: the action image must no longer be the terminal. + */ +describe('#1444 re-glyphed Codev Action', () => { + function action(uuid: string): ManifestAction { + const found = manifest.Actions.find((a) => a.UUID === uuid); + if (!found) throw new Error(`action ${uuid} not in manifest`); + return found; + } + + it('keeps the action referencing its own icon filenames', () => { + const a = action('com.cluesmith.codev.action'); + expect(a.Icon).toBe('icons/list/action'); + expect(a.States[0].Image).toBe('icons/action'); + }); + + it('action icons ship at the convention sizes', () => { + expect(pngSize(join(pluginDir, 'icons/action.png'))).toEqual({ w: 72, h: 72 }); + expect(pngSize(join(pluginDir, 'icons/action@2x.png'))).toEqual({ w: 144, h: 144 }); + expect(pngSize(join(pluginDir, 'icons/list/action.png'))).toEqual({ w: 20, h: 20 }); + expect(pngSize(join(pluginDir, 'icons/list/action@2x.png'))).toEqual({ w: 40, h: 40 }); + }); + + // The collision the issue reports: before the re-glyph, action and open-terminal drew the same + // terminal picture. The two key faces must no longer be byte-identical. + it.each(['icons/action.png', 'icons/action@2x.png', 'icons/list/action.png', 'icons/list/action@2x.png'])( + '%s no longer collides with the open-terminal asset', + (ref) => { + const terminalRef = ref.replace('action', 'open-terminal'); + const actionBytes = readFileSync(join(pluginDir, ref)); + const terminalBytes = readFileSync(join(pluginDir, terminalRef)); + expect(actionBytes.equals(terminalBytes)).toBe(false); + }, + ); +}); diff --git a/apps/streamdeck/src/__tests__/render-action-icons.test.ts b/apps/streamdeck/src/__tests__/render-action-icons.test.ts index 545ea3d20..7d0222dfe 100644 --- a/apps/streamdeck/src/__tests__/render-action-icons.test.ts +++ b/apps/streamdeck/src/__tests__/render-action-icons.test.ts @@ -3,7 +3,7 @@ import { readFileSync } from 'node:fs'; import { join, dirname } from 'node:path'; import { fileURLToPath } from 'node:url'; // @ts-expect-error — plain ESM build script, no type declarations. -import { ICONS, extractGlyph } from '../../scripts/render-action-icons.mjs'; +import { ICONS, BRAND_ICONS, extractGlyph, extractBrandMark } from '../../scripts/render-action-icons.mjs'; /** * #1440: the action icons are rendered FROM face.ts's GLYPHS map, not re-drawn — the render @@ -13,6 +13,10 @@ import { ICONS, extractGlyph } from '../../scripts/render-action-icons.mjs'; */ const root = join(dirname(fileURLToPath(import.meta.url)), '..', '..'); const faceSrc = readFileSync(join(root, 'src', 'face.ts'), 'utf-8'); +const pluginSvg = readFileSync( + join(root, 'com.cluesmith.codev.sdPlugin', 'icons', 'plugin.svg'), + 'utf-8', +); describe('extractGlyph pulls the glyph vector out of face.ts', () => { for (const { name, glyph } of ICONS) { @@ -35,3 +39,35 @@ describe('extractGlyph pulls the glyph vector out of face.ts', () => { expect(svg).toContain(' { + it('routes the catch-all action through the brand source, not a glyph', () => { + expect(BRAND_ICONS).toEqual([{ name: 'action' }]); + // The re-glyph must not reintroduce a glyph source for `action`. + expect(ICONS.some((i: { name: string }) => i.name === 'action')).toBe(false); + }); + + it('returns the mark group and the svg viewBox', () => { + const mark = extractBrandMark(pluginSvg); + expect(mark.viewBox).toMatch(/^[\d.\s]+$/); + expect(mark.inner).toMatch(/^ { + const mark = extractBrandMark(pluginSvg); + expect(mark.inner).not.toContain(' { + expect(() => extractBrandMark('')).toThrow(/brand mark/); + }); +}); diff --git a/codev/state/air-1444_thread.md b/codev/state/air-1444_thread.md new file mode 100644 index 000000000..2f4525658 --- /dev/null +++ b/codev/state/air-1444_thread.md @@ -0,0 +1,29 @@ +# air-1444 — Stream Deck: re-glyph the catch-all Codev Action + +## Issue +`Codev Action` (catch-all verb runner) draws a **terminal** glyph (`icons/action.*`). +#1440 gave the new `open-terminal` action its own terminal-glyph icon. The two now look +near-identical in the Stream Deck action picker. Re-glyph the catch-all, not open-terminal. + +## Verification (issue point 3) — done before coding +`CodevAction` (src/actions.ts:63-66) extends `VerbKey` and does NOT override `onWillAppear`. +Only `DevServerAction`/`BuilderAction`/gate keys composite a runtime face via `setImage`. +So the Codev Action key face shows the manifest `States[0].Image` (`icons/action`) directly. +=> The change is NOT picker-only: it fixes both the picker list icon AND the physical key face. + +## Approach +- Source: the existing Codev brand mark `icons/plugin.svg` (architect's first candidate). + Prototyped the render at 72 / 20px — the handshake mark is legible and unambiguously + not-a-terminal even at 20x20. It survives; no new artwork needed. +- Extend `scripts/render-action-icons.mjs` (from #1440) rather than hand-rolling: add a + brand-mark source path alongside the glyph source, reuse the same fit fractions + (KEY_FILL 0.56, LIST_FILL 0.94) and render targets (72/144/20/40). +- No manifest change: `Codev Action` already references `icons/list/action` + `icons/action`; + only the pixels behind those filenames change. + +## Status +- [x] Verify runtime render path +- [x] Prototype brand-mark legibility at 20px +- [ ] Extend render script + regenerate action PNGs +- [ ] Tests +- [ ] PR with review in body From c0e78411b168203906addbf49f8c0c140ac7c05a Mon Sep 17 00:00:00 2001 From: Amr Elsayed Date: Fri, 14 Aug 2026 10:55:13 +1000 Subject: [PATCH 3/7] =?UTF-8?q?[Air=20#1444]=20docs:=20update=20builder=20?= =?UTF-8?q?thread=20=E2=80=94=20PR=20#1453=20opened?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- codev/state/air-1444_thread.md | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/codev/state/air-1444_thread.md b/codev/state/air-1444_thread.md index 2f4525658..b96a4e58c 100644 --- a/codev/state/air-1444_thread.md +++ b/codev/state/air-1444_thread.md @@ -24,6 +24,13 @@ So the Codev Action key face shows the manifest `States[0].Image` (`icons/action ## Status - [x] Verify runtime render path - [x] Prototype brand-mark legibility at 20px -- [ ] Extend render script + regenerate action PNGs -- [ ] Tests -- [ ] PR with review in body +- [x] Extend render script + regenerate action PNGs (brand-mark source in render-action-icons.mjs) +- [x] Tests (172 pass; check-types + build green after building @cluesmith/codev-sdk first) +- [x] PR #1453 with review in body + +## Notes +- send-queue/open-terminal PNGs re-encode with different IM metadata but are pixel-identical + (AE=0) to #1440's committed versions; reverted them so the diff is action-only. +- check-types/build initially failed on missing @cluesmith/codev-sdk/controller — pre-existing, + fixed by `pnpm --filter @cluesmith/codev-sdk build` (dist wasn't built in the worktree). +- No CMAP: AIR economy, purely declarative asset regen, visually + test-guarded. From b759acd4c4e1cf040a4a3088a81b0529168b8791 Mon Sep 17 00:00:00 2001 From: Amr Elsayed Date: Fri, 14 Aug 2026 10:55:15 +1000 Subject: [PATCH 4/7] chore(porch): 1444 record PR #1453 --- .../1444-stream-deck-re-glyph-the-catch/status.yaml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/codev/projects/1444-stream-deck-re-glyph-the-catch/status.yaml b/codev/projects/1444-stream-deck-re-glyph-the-catch/status.yaml index 6a6e0511b..3fe00f864 100644 --- a/codev/projects/1444-stream-deck-re-glyph-the-catch/status.yaml +++ b/codev/projects/1444-stream-deck-re-glyph-the-catch/status.yaml @@ -11,4 +11,9 @@ iteration: 1 build_complete: false history: [] started_at: '2026-08-14T00:27:27.654Z' -updated_at: '2026-08-14T00:27:27.655Z' +updated_at: '2026-08-14T00:55:15.071Z' +pr_history: + - phase: implement + pr_number: 1453 + branch: builder/air-1444 + created_at: '2026-08-14T00:55:15.071Z' From 1d7c7ec2401b9aecb3f47e39365431696c3b6609 Mon Sep 17 00:00:00 2001 From: Amr Elsayed Date: Fri, 14 Aug 2026 10:56:39 +1000 Subject: [PATCH 5/7] chore(porch): 1444 pr phase-transition --- .../projects/1444-stream-deck-re-glyph-the-catch/status.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/codev/projects/1444-stream-deck-re-glyph-the-catch/status.yaml b/codev/projects/1444-stream-deck-re-glyph-the-catch/status.yaml index 3fe00f864..7c510c162 100644 --- a/codev/projects/1444-stream-deck-re-glyph-the-catch/status.yaml +++ b/codev/projects/1444-stream-deck-re-glyph-the-catch/status.yaml @@ -1,7 +1,7 @@ id: '1444' title: stream-deck-re-glyph-the-catch protocol: air -phase: implement +phase: pr plan_phases: [] current_plan_phase: null gates: @@ -11,7 +11,7 @@ iteration: 1 build_complete: false history: [] started_at: '2026-08-14T00:27:27.654Z' -updated_at: '2026-08-14T00:55:15.071Z' +updated_at: '2026-08-14T00:56:39.366Z' pr_history: - phase: implement pr_number: 1453 From de85b8d5c315d73ddefed6645c791ba8e992fcb0 Mon Sep 17 00:00:00 2001 From: Amr Elsayed Date: Fri, 14 Aug 2026 10:56:52 +1000 Subject: [PATCH 6/7] chore(porch): 1444 pr gate-requested --- .../projects/1444-stream-deck-re-glyph-the-catch/status.yaml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/codev/projects/1444-stream-deck-re-glyph-the-catch/status.yaml b/codev/projects/1444-stream-deck-re-glyph-the-catch/status.yaml index 7c510c162..51d31a32e 100644 --- a/codev/projects/1444-stream-deck-re-glyph-the-catch/status.yaml +++ b/codev/projects/1444-stream-deck-re-glyph-the-catch/status.yaml @@ -7,13 +7,15 @@ current_plan_phase: null gates: pr: status: pending + requested_at: '2026-08-14T00:56:52.006Z' iteration: 1 build_complete: false history: [] started_at: '2026-08-14T00:27:27.654Z' -updated_at: '2026-08-14T00:56:39.366Z' +updated_at: '2026-08-14T00:56:52.007Z' pr_history: - phase: implement pr_number: 1453 branch: builder/air-1444 created_at: '2026-08-14T00:55:15.071Z' +pr_ready_for_human: true From 5c048c25ea9ce32272c7e170a48ca9a4e1686a7d Mon Sep 17 00:00:00 2001 From: Amr Elsayed Date: Sat, 15 Aug 2026 11:52:51 +1000 Subject: [PATCH 7/7] chore(porch): 1444 pr gate-approved --- .../1444-stream-deck-re-glyph-the-catch/status.yaml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/codev/projects/1444-stream-deck-re-glyph-the-catch/status.yaml b/codev/projects/1444-stream-deck-re-glyph-the-catch/status.yaml index 51d31a32e..249eac78c 100644 --- a/codev/projects/1444-stream-deck-re-glyph-the-catch/status.yaml +++ b/codev/projects/1444-stream-deck-re-glyph-the-catch/status.yaml @@ -6,16 +6,17 @@ plan_phases: [] current_plan_phase: null gates: pr: - status: pending + status: approved requested_at: '2026-08-14T00:56:52.006Z' + approved_at: '2026-08-15T01:52:51.230Z' iteration: 1 build_complete: false history: [] started_at: '2026-08-14T00:27:27.654Z' -updated_at: '2026-08-14T00:56:52.007Z' +updated_at: '2026-08-15T01:52:51.230Z' pr_history: - phase: implement pr_number: 1453 branch: builder/air-1444 created_at: '2026-08-14T00:55:15.071Z' -pr_ready_for_human: true +pr_ready_for_human: false