@litfamily/litopencode 1.0.4 → 1.0.6

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 (76) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README-Ko-KR.md +150 -115
  3. package/README.md +147 -116
  4. package/dist/activation-workflow-prompts.js +1 -1
  5. package/dist/agents/registry.js +30 -26
  6. package/dist/cli/args.js +3 -3
  7. package/dist/cli/host-limits.d.ts +1 -1
  8. package/dist/cli/host-limits.js +3 -2
  9. package/dist/cli/install-config.js +2 -2
  10. package/dist/cli/install-report.js +18 -1
  11. package/dist/cli/managed-skill-assets.d.ts +1 -1
  12. package/dist/cli/managed-skill-assets.js +3 -1
  13. package/dist/cli/model-catalog.d.ts +56 -0
  14. package/dist/cli/model-catalog.js +78 -17
  15. package/dist/cli/model-policy.js +7 -6
  16. package/dist/cli/native-skill-integrity.d.ts +16 -0
  17. package/dist/cli/native-skill-integrity.js +80 -0
  18. package/dist/cli/native-skills.d.ts +9 -1
  19. package/dist/cli/native-skills.js +19 -3
  20. package/dist/cli/types.d.ts +6 -1
  21. package/dist/cli.js +8 -7
  22. package/dist/config-parser.js +3 -2
  23. package/dist/config.d.ts +1 -1
  24. package/dist/config.js +13 -12
  25. package/dist/features.d.ts +17 -1
  26. package/dist/features.js +10 -0
  27. package/dist/model-route-policy.d.ts +1 -1
  28. package/dist/model-route-policy.js +24 -7
  29. package/dist/skills.d.ts +8 -1
  30. package/dist/skills.js +8 -0
  31. package/dist/uiux-visual-catalog.js +5 -5
  32. package/docs/assets/cover-motion-still.webp +0 -0
  33. package/docs/assets/cover-motion.webp +0 -0
  34. package/docs/assets/readme/JetBrainsMono-OFL.txt +93 -0
  35. package/docs/assets/readme/Lucide-LICENSE.txt +43 -0
  36. package/docs/assets/readme/ascii-readme.svg +5 -0
  37. package/docs/assets/readme/badge-version.svg +1 -1
  38. package/docs/assets/readme/ignition-film.mp4 +0 -0
  39. package/docs/assets/readme/ignition-readme.gif +0 -0
  40. package/docs/assets/readme/litfamily-machines.png +0 -0
  41. package/docs/assets/readme/lucide-book-open.svg +14 -0
  42. package/docs/assets/readme/lucide-play.svg +13 -0
  43. package/docs/assets/readme/lucide-shield-check.svg +14 -0
  44. package/docs/assets/readme/poster.png +0 -0
  45. package/docs/migration.md +2 -2
  46. package/docs/reference-Ko-KR.md +43 -4
  47. package/docs/reference.md +51 -10
  48. package/package.json +1 -1
  49. package/skills/frontend-ui-ux/SKILL.md +25 -31
  50. package/skills/frontend-ui-ux/references/complete-contract.md +12 -12
  51. package/skills/frontend-ui-ux/references/default-editorial-pixel.json +19 -0
  52. package/skills/frontend-ui-ux/references/production.md +15 -0
  53. package/skills/managed-skill-manifest.json +92 -1
  54. package/skills/readme-studio/SKILL.md +76 -0
  55. package/skills/readme-studio/references/decoration-patterns.md +105 -0
  56. package/skills/readme-studio/references/motion.md +38 -0
  57. package/skills/readme-studio/references/production.md +13 -0
  58. package/skills/readme-studio/references/typography.md +16 -0
  59. package/skills/readme-studio/scripts/check-facts.mjs +28 -0
  60. package/skills/readme-studio/templates/cover-source.json +1 -0
  61. package/skills/readme-studio/templates/facts.json +1 -0
  62. package/skills/readme-studio/templates/hyperframes/index.html +62 -0
  63. package/skills/readme-studio/templates/hyperframes/index.motion.json +1 -0
  64. package/skills/readme-studio/templates/hyperframes/package-lock.json +1966 -0
  65. package/skills/readme-studio/templates/hyperframes/package.json +1 -0
  66. package/skills/readme-studio/templates/readme-cover-section.md +53 -0
  67. package/skills/readme-studio/templates/remotion/package-lock.json +3783 -0
  68. package/skills/readme-studio/templates/remotion/package.json +1 -0
  69. package/skills/readme-studio/templates/remotion/src/index.tsx +32 -0
  70. package/skills/readme-studio/templates/typography/files.mjs +46 -0
  71. package/skills/readme-studio/templates/typography/outline.mjs +47 -0
  72. package/skills/readme-studio/templates/typography/package-lock.json +133 -0
  73. package/skills/readme-studio/templates/typography/package.json +1 -0
  74. package/tools/check-pack-payload.mjs +34 -2
  75. package/tools/payload-substance-parity.json +4 -3
  76. package/tools/version-manifests.json +4 -4
@@ -0,0 +1 @@
1
+ {"name":"readme-studio-motion","private":true,"type":"module","scripts":{"compositions":"remotion compositions src/index.tsx"},"dependencies":{"@remotion/cli":"4.0.526","remotion":"4.0.526","react":"19.2.0","react-dom":"19.2.0"}}
@@ -0,0 +1,32 @@
1
+ import React from 'react';
2
+ import {AbsoluteFill, Composition, Img, registerRoot, staticFile, useCurrentFrame, useVideoConfig} from 'remotion';
3
+
4
+ type CoverProps = {dark:boolean; farBlur?:number; middleBlur?:number; grain?:number; glow?:number; depth?:number};
5
+ const pixels=['000111100','001111110','011010111','111111111','011111110','001001100','011001110'];
6
+ function Cover({dark,farBlur=9,middleBlur=2,grain=.04,glow=.18,depth=.025}:CoverProps) {
7
+ const f=useCurrentFrame();const {width,height}=useVideoConfig();const mobile=width<height;
8
+ const phase=f/299, pulse=Math.sin(phase*Math.PI)**2;
9
+ const entry=Math.min(1,f/24), settle=1-(1-entry)**3;
10
+ const exit=f>275?(f-275)/24:0;
11
+ const offset=(1-settle)*12+exit**3*12;
12
+ const ink=dark?'#f4f1e9':'#15242a',field=dark?'#15242a':'#f4f1e9';
13
+ const suffix=dark?'light':'dark';
14
+ return <AbsoluteFill style={{background:field,overflow:'hidden'}}>
15
+ <Img className="depth-plane-far" src={staticFile('background.png')} style={{position:'absolute',width:'100%',height:'100%',objectFit:'cover',filter:`blur(${farBlur}px)`,transform:`scale(${1.04+pulse*depth})`}}/>
16
+ <Img className="depth-plane-middle" src={staticFile('background.png')} style={{position:'absolute',width:'100%',height:'100%',objectFit:'cover',filter:`blur(${middleBlur}px)`,opacity:.68,transform:`scale(${1.03+pulse*depth*.45})`,maskImage:'linear-gradient(to bottom,transparent 5%,black 28%,black 72%,transparent 94%)',WebkitMaskImage:'linear-gradient(to bottom,transparent 5%,black 28%,black 72%,transparent 94%)'}}/>
17
+ <AbsoluteFill style={{background:`radial-gradient(ellipse at 80% 10%,rgba(170,240,196,${glow}),transparent 60%)`}}/>
18
+ <AbsoluteFill className="rim-light" style={{background:'linear-gradient(112deg,transparent 42%,rgba(255,244,196,.04) 46%,rgba(255,239,184,.38) 49%,rgba(255,255,245,.2) 50%,rgba(255,239,184,.08) 53%,transparent 59%)',mixBlendMode:'screen',opacity:.78}}/>
19
+ <svg width={width} height={height} style={{position:'absolute',opacity:grain}}><filter id="grain"><feTurbulence type="fractalNoise" baseFrequency=".8" numOctaves="2" seed="17"/></filter><rect width="100%" height="100%" filter="url(#grain)"/></svg>
20
+ <div className="sharp-foreground" style={{position:'absolute',left:mobile?40:64,top:mobile?48:60,width:mobile?width-80:width*.64,padding:mobile?28:36,boxSizing:'border-box',background:field,color:ink,border:`1px solid ${ink}`,filter:'none',transform:`translateY(${offset}px)`}}>
21
+ <Img src={staticFile(`label-${suffix}.svg`)} style={{width:mobile?'74%':'42%',height:mobile?30:24,objectFit:'contain',objectPosition:'left'}}/>
22
+ <Img src={staticFile(`title-${suffix}.svg`)} style={{display:'block',width:'100%',marginTop:mobile?32:42}}/>
23
+ <Img src={staticFile(`subtitle-${suffix}.svg`)} style={{display:'block',width:'94%',marginTop:24}}/>
24
+ <div style={{height:1,background:ink,marginTop:mobile?32:40,opacity:.35}}/>
25
+ </div>
26
+ <svg viewBox="0 0 9 7" width={mobile?180:240} height={mobile?140:186} style={{position:'absolute',right:mobile?60:80,bottom:mobile?100:68,transform:`translateY(${-pulse*16}px)`,imageRendering:'pixelated'}} shapeRendering="crispEdges" aria-label="Original pixel field sprite">
27
+ {pixels.flatMap((row,y)=>[...row].map((cell,x)=>cell==='1'?<rect key={`${x}-${y}`} x={x} y={y} width="1" height="1" fill={(x+y)%4===0?'#ed734b':'#c9ee95'}/>:null))}
28
+ </svg>
29
+ </AbsoluteFill>;
30
+ }
31
+ function Root(){return <>{[false,true].flatMap(mobile=>[false,true].map(dark=><Composition key={`${mobile}-${dark}`} id={`${mobile?'Mobile':'Wide'}${dark?'Dark':'Light'}`} component={Cover} width={mobile?768:1600} height={mobile?960:800} fps={60} durationInFrames={300} defaultProps={{dark}}/>))}</>;}
32
+ registerRoot(Root);
@@ -0,0 +1,46 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+
4
+ export function canonical(location) {
5
+ const absolute = path.resolve(location);
6
+ const parsed = path.parse(absolute);
7
+ let current = parsed.root;
8
+ for (const part of absolute.slice(parsed.root.length).split(path.sep).filter(Boolean)) {
9
+ current = path.join(current, part);
10
+ if (fs.lstatSync(current).isSymbolicLink()) throw new Error('symlink path refused');
11
+ }
12
+ return fs.realpathSync(absolute);
13
+ }
14
+ export function inside(root, relative) {
15
+ if (typeof relative !== 'string' || !relative || path.isAbsolute(relative) || relative.includes('\\') || relative.split('/').some(x => !x || x === '.' || x === '..')) throw new Error('expected a bounded relative path');
16
+ const base = canonical(root);
17
+ if (!fs.statSync(base).isDirectory()) throw new Error('root must be a directory');
18
+ return path.join(base, relative);
19
+ }
20
+ export function readRegular(location, limit = 1048576) {
21
+ const resolved = canonical(location);
22
+ const before = fs.lstatSync(resolved);
23
+ if (!before.isFile() || before.size === 0 || before.size > limit) throw new Error('expected bounded nonempty regular file');
24
+ const fd = fs.openSync(resolved, fs.constants.O_RDONLY | fs.constants.O_NOFOLLOW | fs.constants.O_NONBLOCK);
25
+ try {
26
+ const stat = fs.fstatSync(fd);
27
+ if (!stat.isFile() || stat.dev !== before.dev || stat.ino !== before.ino || stat.size !== before.size) throw new Error('file changed during read');
28
+ const bytes = Buffer.alloc(stat.size + 1);
29
+ const size = fs.readSync(fd, bytes, 0, bytes.length, 0);
30
+ const after = fs.fstatSync(fd);
31
+ if (size !== stat.size || after.mtimeMs !== stat.mtimeMs || after.ctimeMs !== stat.ctimeMs) throw new Error('file changed during read');
32
+ return bytes.subarray(0, size);
33
+ } finally { fs.closeSync(fd); }
34
+ }
35
+ export function writeFresh(root, relative, data) {
36
+ const file = inside(root, relative);
37
+ const parent = canonical(path.dirname(file));
38
+ const before = fs.statSync(parent);
39
+ const fd = fs.openSync(file, fs.constants.O_WRONLY | fs.constants.O_CREAT | fs.constants.O_EXCL | fs.constants.O_NOFOLLOW, 0o644);
40
+ try {
41
+ const after = fs.statSync(canonical(parent));
42
+ if (before.dev !== after.dev || before.ino !== after.ino) throw new Error('output parent changed');
43
+ fs.writeFileSync(fd, data);
44
+ } finally { fs.closeSync(fd); }
45
+ return file;
46
+ }
@@ -0,0 +1,47 @@
1
+ import {createHash} from 'node:crypto';
2
+ import {parseArgs} from 'node:util';
3
+ import {pathToFileURL} from 'node:url';
4
+ import {readRegular, writeFresh} from './files.mjs';
5
+ const xml = text => String(text).replace(/[&<>"']/g, c => ({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&apos;'}[c]));
6
+ const finite = values => { if (!values.every(Number.isFinite)) throw new Error('invalid finite glyph geometry'); };
7
+
8
+ export function outline(font, text, fill = '#15242a', size = 100) {
9
+ if (typeof text !== 'string' || !text.trim() || [...text].length > 500 || /[\x00-\x1f]/u.test(text) || !/^#[a-f0-9]{6}$/i.test(fill) || !Number.isFinite(size) || size <= 0 || size > 512) throw new Error('invalid text, size or fill');
10
+ finite([font.unitsPerEm,font.ascent,font.descent]);
11
+ if (font.unitsPerEm <= 0 || font.ascent <= font.descent) throw new Error('invalid font metrics');
12
+ for (const c of text) if (!font.hasGlyphForCodePoint(c.codePointAt(0))) throw new Error(`missing glyph U+${c.codePointAt(0).toString(16)}`);
13
+ const run = font.layout(text);
14
+ if (!run.glyphs.length || run.glyphs.length !== run.positions.length) throw new Error('invalid shaped run');
15
+ let x=0,y=0,minX=0,maxX=0,minY=font.descent,maxY=font.ascent;
16
+ const paths=[];
17
+ run.glyphs.forEach((glyph,i) => {
18
+ const p=run.positions[i];finite([p.xAdvance,p.yAdvance,p.xOffset,p.yOffset]);
19
+ if (!glyph.id) throw new Error('missing shaped glyph');
20
+ const d=glyph.path.toSVG();
21
+ if (typeof d !== 'string') throw new Error('missing outline');
22
+ const gx=x+p.xOffset, gy=y+p.yOffset;
23
+ if (d) {
24
+ const b=glyph.bbox;finite([b.minX,b.maxX,b.minY,b.maxY]);
25
+ if(b.minX>b.maxX || b.minY>b.maxY) throw new Error('invalid glyph bounds');
26
+ minX=Math.min(minX,gx+b.minX);maxX=Math.max(maxX,gx+b.maxX);
27
+ minY=Math.min(minY,gy+b.minY);maxY=Math.max(maxY,gy+b.maxY);
28
+ paths.push(`<path d="${xml(d)}" transform="translate(${gx} ${gy})"/>`);
29
+ }
30
+ x+=p.xAdvance;y+=p.yAdvance;finite([x,y]);minX=Math.min(minX,x);maxX=Math.max(maxX,x);
31
+ });
32
+ const scale=size/font.unitsPerEm,pad=size*.08,width=(maxX-minX)*scale+pad*2,height=(maxY-minY)*scale+pad*2;
33
+ finite([width,height]);if(width<=0 || height<=0) throw new Error('invalid bounds');
34
+ return `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 ${width} ${height}" role="img"><title>${xml(text)}</title><g fill="${fill}" transform="translate(${pad-minX*scale} ${pad+maxY*scale}) scale(${scale} ${-scale})">${paths.join('')}</g></svg>\n`;
35
+ }
36
+ if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
37
+ try {
38
+ const {values:v}=parseArgs({options:Object.fromEntries(['font','family','license','text','root','output','fill','size'].map(k=>[k,{type:'string'}]))});
39
+ for(const key of ['font','family','license','text','root','output']) if(!v[key]) throw new Error(`--${key} required`);
40
+ const bytes=readRegular(v.font,64*1048576), license=readRegular(v.license);
41
+ const font=(await import('fontkit')).create(bytes);
42
+ if(font.familyName !== v.family) throw new Error(`font family mismatch: ${font.familyName}`);
43
+ const svg=outline(font,v.text,v.fill, v.size === undefined ? 100 : Number(v.size));
44
+ const output=writeFresh(v.root,v.output,svg);
45
+ console.log(JSON.stringify({output,text:v.text,font:{family:font.familyName,style:font.subfamilyName,version:font.version,sha256:createHash('sha256').update(bytes).digest('hex')},license:{path:v.license,sha256:createHash('sha256').update(license).digest('hex'),review:'manual license verification required'}}));
46
+ } catch(error) {console.error(`readme-studio: ${error.message}`);process.exitCode=1;}
47
+ }
@@ -0,0 +1,133 @@
1
+ {
2
+ "name": "readme-studio-typography",
3
+ "lockfileVersion": 3,
4
+ "requires": true,
5
+ "packages": {
6
+ "": {
7
+ "name": "readme-studio-typography",
8
+ "dependencies": {
9
+ "fontkit": "2.0.4"
10
+ }
11
+ },
12
+ "node_modules/@swc/helpers": {
13
+ "version": "0.5.23",
14
+ "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.23.tgz",
15
+ "integrity": "sha512-5lSsMOTXURePglDfvuAQUqkGek9Hg2kksOYay2m0+XR++b2NWYL/4sWyuvVBIs8oKnJaxkdi9whaL/sqN13afw==",
16
+ "license": "Apache-2.0",
17
+ "dependencies": {
18
+ "tslib": "^2.8.0"
19
+ }
20
+ },
21
+ "node_modules/base64-js": {
22
+ "version": "1.5.1",
23
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
24
+ "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
25
+ "funding": [
26
+ {
27
+ "type": "github",
28
+ "url": "https://github.com/sponsors/feross"
29
+ },
30
+ {
31
+ "type": "patreon",
32
+ "url": "https://www.patreon.com/feross"
33
+ },
34
+ {
35
+ "type": "consulting",
36
+ "url": "https://feross.org/support"
37
+ }
38
+ ],
39
+ "license": "MIT"
40
+ },
41
+ "node_modules/brotli": {
42
+ "version": "1.3.3",
43
+ "resolved": "https://registry.npmjs.org/brotli/-/brotli-1.3.3.tgz",
44
+ "integrity": "sha512-oTKjJdShmDuGW94SyyaoQvAjf30dZaHnjJ8uAF+u2/vGJkJbJPJAT1gDiOJP5v1Zb6f9KEyW/1HpuaWIXtGHPg==",
45
+ "license": "MIT",
46
+ "dependencies": {
47
+ "base64-js": "^1.1.2"
48
+ }
49
+ },
50
+ "node_modules/clone": {
51
+ "version": "2.1.2",
52
+ "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
53
+ "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==",
54
+ "license": "MIT",
55
+ "engines": {
56
+ "node": ">=0.8"
57
+ }
58
+ },
59
+ "node_modules/dfa": {
60
+ "version": "1.2.0",
61
+ "resolved": "https://registry.npmjs.org/dfa/-/dfa-1.2.0.tgz",
62
+ "integrity": "sha512-ED3jP8saaweFTjeGX8HQPjeC1YYyZs98jGNZx6IiBvxW7JG5v492kamAQB3m2wop07CvU/RQmzcKr6bgcC5D/Q==",
63
+ "license": "MIT"
64
+ },
65
+ "node_modules/fast-deep-equal": {
66
+ "version": "3.1.3",
67
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
68
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
69
+ "license": "MIT"
70
+ },
71
+ "node_modules/fontkit": {
72
+ "version": "2.0.4",
73
+ "resolved": "https://registry.npmjs.org/fontkit/-/fontkit-2.0.4.tgz",
74
+ "integrity": "sha512-syetQadaUEDNdxdugga9CpEYVaQIxOwk7GlwZWWZ19//qW4zE5bknOKeMBDYAASwnpaSHKJITRLMF9m1fp3s6g==",
75
+ "license": "MIT",
76
+ "dependencies": {
77
+ "@swc/helpers": "^0.5.12",
78
+ "brotli": "^1.3.2",
79
+ "clone": "^2.1.2",
80
+ "dfa": "^1.2.0",
81
+ "fast-deep-equal": "^3.1.3",
82
+ "restructure": "^3.0.0",
83
+ "tiny-inflate": "^1.0.3",
84
+ "unicode-properties": "^1.4.0",
85
+ "unicode-trie": "^2.0.0"
86
+ }
87
+ },
88
+ "node_modules/pako": {
89
+ "version": "0.2.9",
90
+ "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz",
91
+ "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==",
92
+ "license": "MIT"
93
+ },
94
+ "node_modules/restructure": {
95
+ "version": "3.0.2",
96
+ "resolved": "https://registry.npmjs.org/restructure/-/restructure-3.0.2.tgz",
97
+ "integrity": "sha512-gSfoiOEA0VPE6Tukkrr7I0RBdE0s7H1eFCDBk05l1KIQT1UIKNc5JZy6jdyW6eYH3aR3g5b3PuL77rq0hvwtAw==",
98
+ "license": "MIT"
99
+ },
100
+ "node_modules/tiny-inflate": {
101
+ "version": "1.0.3",
102
+ "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz",
103
+ "integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==",
104
+ "license": "MIT"
105
+ },
106
+ "node_modules/tslib": {
107
+ "version": "2.8.1",
108
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
109
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
110
+ "license": "0BSD"
111
+ },
112
+ "node_modules/unicode-properties": {
113
+ "version": "1.4.1",
114
+ "resolved": "https://registry.npmjs.org/unicode-properties/-/unicode-properties-1.4.1.tgz",
115
+ "integrity": "sha512-CLjCCLQ6UuMxWnbIylkisbRj31qxHPAurvena/0iwSVbQ2G1VY5/HjV0IRabOEbDHlzZlRdCrD4NhB0JtU40Pg==",
116
+ "license": "MIT",
117
+ "dependencies": {
118
+ "base64-js": "^1.3.0",
119
+ "unicode-trie": "^2.0.0"
120
+ }
121
+ },
122
+ "node_modules/unicode-trie": {
123
+ "version": "2.0.0",
124
+ "resolved": "https://registry.npmjs.org/unicode-trie/-/unicode-trie-2.0.0.tgz",
125
+ "integrity": "sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ==",
126
+ "license": "MIT",
127
+ "dependencies": {
128
+ "pako": "^0.2.5",
129
+ "tiny-inflate": "^1.0.0"
130
+ }
131
+ }
132
+ }
133
+ }
@@ -0,0 +1 @@
1
+ {"name":"readme-studio-typography","private":true,"type":"module","dependencies":{"fontkit":"2.0.4"}}
@@ -11,7 +11,7 @@ const FORBIDDEN_PATH_RULES = [
11
11
  { label: "local asset generator", pattern: /^generate_cover\.py$/u },
12
12
  { label: "repository cover PNG", pattern: /^cover\.png$/u },
13
13
  { label: "repository cover vector", pattern: /^docs\/assets\/cover\.svg$/u },
14
- { label: "non-landing README presentation asset", pattern: /^docs\/assets\/readme\/(?!(?:badge-version|badge-license|litopencode-wordmark)\.svg$|litopencode-clay-icon\.png$)/u },
14
+ { label: "unapproved README presentation asset", pattern: /^docs\/assets\/readme\/(?!(?:ascii-readme|badge-version|badge-license|lucide-book-open|lucide-play|lucide-shield-check)\.svg$|litopencode-wordmark\.svg$|litopencode-clay-icon\.png$|(?:litfamily-machines|poster)\.png$|ignition-film\.mp4$|ignition-readme\.gif$|(?:Lucide-LICENSE|JetBrainsMono-OFL)\.txt$)/u },
15
15
  { label: "maintainer release checklist", pattern: /^docs\/release-checklist\.md$/u },
16
16
  { label: "internal recon/spec document", pattern: /^docs\/(?:recon|spec)(\/|$)/u },
17
17
  { label: "implementation plan", pattern: /(^|\/)plans(\/|$)/u },
@@ -32,6 +32,38 @@ const FORBIDDEN_PATH_RULES = [
32
32
 
33
33
  const MANAGED_MANIFEST_PATH = "skills/managed-skill-manifest.json";
34
34
  const MAX_MANAGED_FILE_BYTES = 16 * 1024 * 1024;
35
+ const REQUIRED_README_PATHS = [
36
+ "README.md",
37
+ "README-Ko-KR.md",
38
+ "LICENSE",
39
+ "CHANGELOG.md",
40
+ "CODE_OF_CONDUCT.md",
41
+ "CONTRIBUTING.md",
42
+ "SECURITY.md",
43
+ "SUPPORT.md",
44
+ "docs/lit-mark.md",
45
+ "docs/migration.md",
46
+ "docs/privacy.md",
47
+ "docs/reference-Ko-KR.md",
48
+ "docs/reference.md",
49
+ "docs/assets/cover.webp",
50
+ "docs/assets/cover-motion.webp",
51
+ "docs/assets/cover-motion-still.webp",
52
+ "docs/assets/readme/ascii-readme.svg",
53
+ "docs/assets/readme/badge-license.svg",
54
+ "docs/assets/readme/badge-version.svg",
55
+ "docs/assets/readme/JetBrainsMono-OFL.txt",
56
+ "docs/assets/readme/Lucide-LICENSE.txt",
57
+ "docs/assets/readme/ignition-film.mp4",
58
+ "docs/assets/readme/ignition-readme.gif",
59
+ "docs/assets/readme/litfamily-machines.png",
60
+ "docs/assets/readme/litopencode-clay-icon.png",
61
+ "docs/assets/readme/litopencode-wordmark.svg",
62
+ "docs/assets/readme/lucide-book-open.svg",
63
+ "docs/assets/readme/lucide-play.svg",
64
+ "docs/assets/readme/lucide-shield-check.svg",
65
+ "docs/assets/readme/poster.png"
66
+ ];
35
67
 
36
68
  async function readManagedManifest() {
37
69
  const raw = (await readStableRegularFile(process.cwd(), MANAGED_MANIFEST_PATH, {
@@ -59,7 +91,7 @@ function canonicalPackagePath(id, definition, relativePath) {
59
91
  }
60
92
 
61
93
  function requiredManagedPaths({ skills, vendorFiles }) {
62
- const required = [MANAGED_MANIFEST_PATH, "skills/skill-rename-aliases.json"];
94
+ const required = [...REQUIRED_README_PATHS, MANAGED_MANIFEST_PATH, "skills/skill-rename-aliases.json"];
63
95
  for (const rawAsset of vendorFiles) {
64
96
  const asset = requireObject(rawAsset, "managed-skill manifest vendor asset");
65
97
  if (typeof asset.path !== "string" || typeof asset.sha256 !== "string") {
@@ -160,6 +160,7 @@
160
160
  "lsp",
161
161
  "lsp-setup",
162
162
  "native-goal-verdict",
163
+ "readme-studio",
163
164
  "refactor",
164
165
  "reference-benchmark-claims",
165
166
  "release-guardrails",
@@ -174,8 +175,8 @@
174
175
  "workflow-loop"
175
176
  ],
176
177
  "inventory": {
177
- "count": 40,
178
- "sha256": "526fa688a02750abda27581bd3058c55a7445f825bd8445067ce2abe13758ebd"
178
+ "count": 41,
179
+ "sha256": "99c1c463eea33038c776e4f50ef87ee1c4c5352b71d3f524095de7cd7bd579ff"
179
180
  }
180
181
  },
181
182
  "p33": {
@@ -287,7 +288,7 @@
287
288
  "p27": 209,
288
289
  "p28": 204,
289
290
  "p31": 198,
290
- "p32": 209,
291
+ "p32": 211,
291
292
  "p33": 211
292
293
  }
293
294
  },
@@ -11,14 +11,14 @@
11
11
  {
12
12
  "path": "README-Ko-KR.md",
13
13
  "kind": "pinned",
14
- "occurrences": 11,
15
- "why": "The landing page identifies the current checkout version; the repository-owned cover is version-free."
14
+ "occurrences": 47,
15
+ "why": "The bilingual landing pages pin artwork and package links to the current package version."
16
16
  },
17
17
  {
18
18
  "path": "README.md",
19
19
  "kind": "pinned",
20
- "occurrences": 11,
21
- "why": "The landing page identifies the current checkout version; the repository-owned cover is version-free."
20
+ "occurrences": 46,
21
+ "why": "The bilingual landing pages pin artwork and package links to the current package version."
22
22
  },
23
23
  {
24
24
  "path": "docs/assets/readme/badge-version.svg",