👁️
5
fork

Configure Feed

Select the types of activity you want to include in your feed.

add goat to pipeline, patch out the large string warning

+81 -19
+2 -1
.claude/settings.local.json
··· 63 63 "Bash(ls:*)", 64 64 "Bash(npm run screenshot:wireframe:*)", 65 65 "Bash(curl:*)", 66 - "Bash(npm run build:lexicons:*)" 66 + "Bash(npm run build:lexicons:*)", 67 + "Bash(npm run lexicons:lint:*)" 67 68 ], 68 69 "deny": [], 69 70 "ask": []
+5 -2
CLAUDE.md
··· 73 73 - **Generated TS**: `src/lib/lexicons/` - TypeScript types from lexicons 74 74 - After modifying `.tsp` files, run `npm run lexicons:all` which: 75 75 1. `lexicons:compile` - compiles TypeSpec → JSON lexicons 76 - 2. `lexicons:codegen` - generates TypeScript types from JSON lexicons 77 - 3. `lexicons:scopes` - updates OAuth scopes in `public/client-metadata.json` 76 + 2. `lexicons:lint` - lints lexicons with `goat lex lint` 77 + 3. `lexicons:codegen` - generates TypeScript types from JSON lexicons 78 + 4. `lexicons:scopes` - updates OAuth scopes in `public/client-metadata.json` 78 79 - Lexicons follow AT Protocol conventions (used for ATProto/Bluesky integrations) 80 + 81 + **IMPORTANT**: NEVER edit files in `lexicons/` directly - they are generated from TypeSpec. Edit the `.tsp` files in `typelex/` and run `npm run lexicons:all` to regenerate. 79 82 80 83 ### Styling 81 84
+3 -3
flake.lock
··· 2 2 "nodes": { 3 3 "nixpkgs": { 4 4 "locked": { 5 - "lastModified": 1761236834, 6 - "narHash": "sha256-+pthv6hrL5VLW2UqPdISGuLiUZ6SnAXdd2DdUE+fV2Q=", 5 + "lastModified": 1768875095, 6 + "narHash": "sha256-dYP3DjiL7oIiiq3H65tGIXXIT1Waiadmv93JS0sS+8A=", 7 7 "owner": "NixOS", 8 8 "repo": "nixpkgs", 9 - "rev": "d5faa84122bc0a1fd5d378492efce4e289f8eac1", 9 + "rev": "ed142ab1b3a092c4d149245d0c4126a5d7ea00b0", 10 10 "type": "github" 11 11 }, 12 12 "original": {
+26 -1
flake.nix
··· 13 13 utils.lib.eachDefaultSystem ( 14 14 system: 15 15 let 16 - pkgs = import nixpkgs { inherit system; }; 16 + pkgs = import nixpkgs { 17 + inherit system; 18 + overlays = [ 19 + (final: prev: { 20 + atproto-goat = prev.atproto-goat.overrideAttrs (old: { 21 + # Patch vendored indigo to remove large-string lint warning 22 + # (we intentionally use large strings for long-form richtext content) 23 + preBuild = 24 + (old.preBuild or "") 25 + + '' 26 + if [ -d vendor ]; then 27 + chmod -R u+w vendor 28 + lintFile=vendor/github.com/bluesky-social/indigo/lex/lexlint/lint.go 29 + # Verify the pattern exists before patching 30 + grep -q 'large-string' "$lintFile" || (echo "ERROR: large-string check not found in lint.go - pattern may have changed" && exit 1) 31 + # Remove the large-string check 32 + sed -i '/if v.MaxLength != nil && \*v.MaxLength > 20\*1024/,/^[[:space:]]*}$/d' "$lintFile" 33 + # Verify it was removed 34 + ! grep -q 'large-string' "$lintFile" || (echo "ERROR: failed to remove large-string check" && exit 1) 35 + fi 36 + ''; 37 + }); 38 + }) 39 + ]; 40 + }; 17 41 in 18 42 { 19 43 devShell = ··· 24 48 typescript 25 49 just 26 50 jq 51 + atproto-goat 27 52 cacert # CA certificates for TLS verification 28 53 # language servers 29 54 typescript-language-server
+14 -7
lexicons/com/deckbelcher/deck/list.json
··· 66 66 "description": "Number of copies in the deck." 67 67 }, 68 68 "section": { 69 - "type": "string", 70 - "knownValues": [ 71 - "mainboard", 72 - "sideboard", 73 - "maybeboard", 74 - "commander" 75 - ], 69 + "type": "ref", 70 + "ref": "#section", 76 71 "description": "Which section of the deck this card belongs to. Extensible to support format-specific sections." 77 72 }, 78 73 "tags": { ··· 93 88 "quantity", 94 89 "section" 95 90 ] 91 + }, 92 + "section": { 93 + "type": "string", 94 + "knownValues": [ 95 + "mainboard", 96 + "sideboard", 97 + "maybeboard", 98 + "commander" 99 + ], 100 + "maxLength": 640, 101 + "maxGraphemes": 64, 102 + "description": "Which section of the deck this card belongs to. Extensible to support format-specific sections." 96 103 } 97 104 } 98 105 }
+3 -1
package.json
··· 18 18 "typecheck": "tsc --noEmit", 19 19 "typecheck:faster": "npm run typecheck -- --skipLibCheck --incremental", 20 20 "lexicons:compile": "typelex compile com.deckbelcher.*", 21 + "lexicons:lint": "goat lex lint", 22 + "lexicons:breaking": "goat lex breaking", 21 23 "lexicons:codegen": "lex-cli generate -c ./lex.config.js", 22 24 "lexicons:scopes": "node --experimental-strip-types scripts/generate-oauth-scopes.ts", 23 - "lexicons:all": "npm run lexicons:compile && npm run lexicons:codegen && npm run lexicons:scopes", 25 + "lexicons:all": "npm run lexicons:compile && npm run lexicons:lint && npm run lexicons:codegen && npm run lexicons:scopes", 24 26 "download:scryfall": "node --experimental-strip-types scripts/download-scryfall.ts" 25 27 }, 26 28 "dependencies": {
+16 -3
src/lib/lexicons/types/com/deckbelcher/deck/list.ts
··· 24 24 /** 25 25 * Which section of the deck this card belongs to. Extensible to support format-specific sections. 26 26 */ 27 - section: /*#__PURE__*/ v.string< 28 - "commander" | "mainboard" | "maybeboard" | "sideboard" | (string & {}) 29 - >(), 27 + get section() { 28 + return sectionSchema; 29 + }, 30 30 /** 31 31 * User annotations for this card in this deck (e.g., "removal", "wincon", "ramp"). 32 32 * @maxLength 128 ··· 89 89 updatedAt: /*#__PURE__*/ v.optional(/*#__PURE__*/ v.datetimeString()), 90 90 }), 91 91 ); 92 + const _sectionSchema = /*#__PURE__*/ v.constrain( 93 + /*#__PURE__*/ v.string< 94 + "commander" | "mainboard" | "maybeboard" | "sideboard" | (string & {}) 95 + >(), 96 + [ 97 + /*#__PURE__*/ v.stringLength(0, 640), 98 + /*#__PURE__*/ v.stringGraphemes(0, 64), 99 + ], 100 + ); 92 101 93 102 type card$schematype = typeof _cardSchema; 94 103 type main$schematype = typeof _mainSchema; 104 + type section$schematype = typeof _sectionSchema; 95 105 96 106 export interface cardSchema extends card$schematype {} 97 107 export interface mainSchema extends main$schematype {} 108 + export interface sectionSchema extends section$schematype {} 98 109 99 110 export const cardSchema = _cardSchema as cardSchema; 100 111 export const mainSchema = _mainSchema as mainSchema; 112 + export const sectionSchema = _sectionSchema as sectionSchema; 101 113 102 114 export interface Card extends v.InferInput<typeof cardSchema> {} 103 115 export interface Main extends v.InferInput<typeof mainSchema> {} 116 + export type Section = v.InferInput<typeof sectionSchema>; 104 117 105 118 declare module "@atcute/lexicons/ambient" { 106 119 interface Records {
+12 -1
typelex/deck-list.tsp
··· 38 38 @maxLength(640) 39 39 scalar CardTag extends string; 40 40 41 + /** Which section of the deck this card belongs to. Extensible to support format-specific sections. */ 42 + @maxGraphemes(64) 43 + @maxLength(640) 44 + union Section { 45 + "mainboard", 46 + "sideboard", 47 + "maybeboard", 48 + "commander", 49 + string, 50 + } 51 + 41 52 /** A card entry in a decklist. */ 42 53 model Card { 43 54 /** Reference to the card (scryfall printing + oracle card). */ ··· 51 62 52 63 /** Which section of the deck this card belongs to. Extensible to support format-specific sections. */ 53 64 @required 54 - section: "mainboard" | "sideboard" | "maybeboard" | "commander" | string; 65 + section: Section; 55 66 56 67 /** User annotations for this card in this deck (e.g., "removal", "wincon", "ramp"). */ 57 68 @maxItems(128)