ridgeline 0.7.5 → 0.7.11

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 (108) hide show
  1. package/README.md +2 -0
  2. package/dist/agents/core/designer.md +18 -0
  3. package/dist/agents/core/planner.md +32 -0
  4. package/dist/agents/core/retrospective.md +64 -0
  5. package/dist/catalog/build-catalog.d.ts +21 -0
  6. package/dist/catalog/build-catalog.js +305 -0
  7. package/dist/catalog/build-catalog.js.map +1 -0
  8. package/dist/catalog/classify.d.ts +16 -0
  9. package/dist/catalog/classify.js +189 -0
  10. package/dist/catalog/classify.js.map +1 -0
  11. package/dist/catalog/extract-metadata.d.ts +41 -0
  12. package/dist/catalog/extract-metadata.js +175 -0
  13. package/dist/catalog/extract-metadata.js.map +1 -0
  14. package/dist/catalog/pack-sprites.d.ts +8 -0
  15. package/dist/catalog/pack-sprites.js +106 -0
  16. package/dist/catalog/pack-sprites.js.map +1 -0
  17. package/dist/catalog/parse-conventions.d.ts +25 -0
  18. package/dist/catalog/parse-conventions.js +86 -0
  19. package/dist/catalog/parse-conventions.js.map +1 -0
  20. package/dist/catalog/resolve-asset-dir.d.ts +15 -0
  21. package/dist/catalog/resolve-asset-dir.js +96 -0
  22. package/dist/catalog/resolve-asset-dir.js.map +1 -0
  23. package/dist/catalog/types.d.ts +74 -0
  24. package/dist/catalog/types.js +3 -0
  25. package/dist/catalog/types.js.map +1 -0
  26. package/dist/catalog/vision-describe.d.ts +12 -0
  27. package/dist/catalog/vision-describe.js +158 -0
  28. package/dist/catalog/vision-describe.js.map +1 -0
  29. package/dist/cli.js +54 -1
  30. package/dist/cli.js.map +1 -1
  31. package/dist/commands/build.d.ts +2 -2
  32. package/dist/commands/build.js +156 -30
  33. package/dist/commands/build.js.map +1 -1
  34. package/dist/commands/catalog.d.ts +6 -0
  35. package/dist/commands/catalog.js +141 -0
  36. package/dist/commands/catalog.js.map +1 -0
  37. package/dist/commands/design.js +73 -0
  38. package/dist/commands/design.js.map +1 -1
  39. package/dist/commands/retrospective.d.ts +7 -0
  40. package/dist/commands/retrospective.js +119 -0
  41. package/dist/commands/retrospective.js.map +1 -0
  42. package/dist/config.js +1 -0
  43. package/dist/config.js.map +1 -1
  44. package/dist/engine/discovery/agent.registry.d.ts +3 -0
  45. package/dist/engine/discovery/agent.registry.js +15 -2
  46. package/dist/engine/discovery/agent.registry.js.map +1 -1
  47. package/dist/engine/pipeline/build.exec.d.ts +1 -1
  48. package/dist/engine/pipeline/build.exec.js +24 -27
  49. package/dist/engine/pipeline/build.exec.js.map +1 -1
  50. package/dist/engine/pipeline/ensemble.exec.d.ts +12 -0
  51. package/dist/engine/pipeline/ensemble.exec.js +123 -30
  52. package/dist/engine/pipeline/ensemble.exec.js.map +1 -1
  53. package/dist/engine/pipeline/phase.graph.d.ts +31 -0
  54. package/dist/engine/pipeline/phase.graph.js +102 -0
  55. package/dist/engine/pipeline/phase.graph.js.map +1 -0
  56. package/dist/engine/pipeline/phase.sequence.d.ts +3 -1
  57. package/dist/engine/pipeline/phase.sequence.js +50 -21
  58. package/dist/engine/pipeline/phase.sequence.js.map +1 -1
  59. package/dist/engine/pipeline/pipeline.shared.d.ts +12 -5
  60. package/dist/engine/pipeline/pipeline.shared.js +50 -26
  61. package/dist/engine/pipeline/pipeline.shared.js.map +1 -1
  62. package/dist/engine/pipeline/plan.exec.d.ts +4 -1
  63. package/dist/engine/pipeline/plan.exec.js +15 -12
  64. package/dist/engine/pipeline/plan.exec.js.map +1 -1
  65. package/dist/engine/pipeline/prompt.document.d.ts +28 -0
  66. package/dist/engine/pipeline/prompt.document.js +50 -0
  67. package/dist/engine/pipeline/prompt.document.js.map +1 -0
  68. package/dist/engine/pipeline/refine.exec.js +14 -14
  69. package/dist/engine/pipeline/refine.exec.js.map +1 -1
  70. package/dist/engine/pipeline/research.exec.d.ts +0 -2
  71. package/dist/engine/pipeline/research.exec.js +31 -58
  72. package/dist/engine/pipeline/research.exec.js.map +1 -1
  73. package/dist/engine/pipeline/review.exec.d.ts +1 -1
  74. package/dist/engine/pipeline/review.exec.js +23 -31
  75. package/dist/engine/pipeline/review.exec.js.map +1 -1
  76. package/dist/engine/pipeline/specify.exec.js +15 -24
  77. package/dist/engine/pipeline/specify.exec.js.map +1 -1
  78. package/dist/engine/pipeline/worktree.parallel.d.ts +22 -0
  79. package/dist/engine/pipeline/worktree.parallel.js +122 -0
  80. package/dist/engine/pipeline/worktree.parallel.js.map +1 -0
  81. package/dist/flavours/web-game/core/builder.md +5 -2
  82. package/dist/flavours/web-game/core/designer.md +157 -0
  83. package/dist/git.js +11 -4
  84. package/dist/git.js.map +1 -1
  85. package/dist/stores/budget.js +21 -17
  86. package/dist/stores/budget.js.map +1 -1
  87. package/dist/stores/handoff.d.ts +4 -0
  88. package/dist/stores/handoff.js +28 -1
  89. package/dist/stores/handoff.js.map +1 -1
  90. package/dist/stores/phases.d.ts +8 -0
  91. package/dist/stores/phases.js +23 -2
  92. package/dist/stores/phases.js.map +1 -1
  93. package/dist/stores/settings.d.ts +1 -0
  94. package/dist/stores/settings.js.map +1 -1
  95. package/dist/stores/state.d.ts +6 -1
  96. package/dist/stores/state.js +101 -19
  97. package/dist/stores/state.js.map +1 -1
  98. package/dist/types.d.ts +3 -0
  99. package/dist/ui/logger.d.ts +11 -0
  100. package/dist/ui/logger.js +71 -0
  101. package/dist/ui/logger.js.map +1 -0
  102. package/dist/ui/output.d.ts +1 -0
  103. package/dist/ui/output.js +11 -1
  104. package/dist/ui/output.js.map +1 -1
  105. package/dist/utils/file-lock.d.ts +5 -0
  106. package/dist/utils/file-lock.js +95 -0
  107. package/dist/utils/file-lock.js.map +1 -0
  108. package/package.json +6 -3
package/README.md CHANGED
@@ -42,6 +42,8 @@ tracks costs, and supports resumable execution when things go wrong.
42
42
  npm install -g ridgeline
43
43
  ```
44
44
 
45
+ **Platform:** macOS and Linux. Windows is not supported.
46
+
45
47
  Ridgeline requires the [Claude CLI](https://docs.anthropic.com/en/docs/claude-code)
46
48
  to be installed and authenticated.
47
49
 
@@ -53,12 +53,22 @@ Round 1 — Art Direction:
53
53
  - Art style: pixel art, vector, 3D, hand-drawn, realistic
54
54
  - Color palette: mood, saturation level, palette constraints
55
55
  - Asset dimensions: sprite sizes, texture resolutions, canvas size
56
+ - Shape language: proportions (chunky/slim), corners (rounded/sharp), detail level
57
+ - Rendering: pixel scale, scaling mode (nearest/bilinear), canvas size
56
58
 
57
59
  Round 2 — UI & HUD:
58
60
 
59
61
  - HUD/overlay style: transparency, position, font choices
60
62
  - Menu design: navigation patterns, transition styles
61
63
  - In-game text: dialogue boxes, tooltips, damage numbers
64
+ - Layout regions: where health, score, inventory, and action buttons go
65
+ - Mood: overall atmosphere and tone in a brief phrase
66
+
67
+ Round 3 — Asset Integration (when asset catalog data is in context):
68
+
69
+ - Asset manifest review: confirm discovered assets match creative intent
70
+ - Background treatment: mood, parallax, scroll behavior for each background
71
+ - Asset loading strategy: preload vs lazy, atlas format, base path
62
72
 
63
73
  **For print-layout projects:**
64
74
 
@@ -129,3 +139,11 @@ The format is flexible — brand guidelines, informal notes, formal style guides
129
139
  **Respect existing design.md.** If one exists, read it as starting context. Offer to refine or extend, don't start from scratch unless asked.
130
140
 
131
141
  **Stay in design territory.** Don't ask about code architecture, error handling, or implementation details. Those belong to the shaper and specifier.
142
+
143
+ **When asset catalog data is present in context:**
144
+
145
+ - Propose palette, style, resolution, and scaling defaults derived from the catalog's visual identity analysis. Include these as `suggestedAnswer` values.
146
+ - Present the asset manifest summary for user confirmation.
147
+ - Use layout region data (if available) to propose HUD/menu arrangements.
148
+ - Flag any catalog warnings about palette mismatches for user review.
149
+ - Cover asset loading strategy (preload/lazy, format, base path) in your questions.
@@ -65,6 +65,38 @@ Every phase file must follow this structure exactly:
65
65
  <Relevant sections of spec.md for this phase, quoted or summarized.>
66
66
  ```
67
67
 
68
+ ## Phase Dependencies (Parallel Execution)
69
+
70
+ Phases can declare dependencies to enable parallel execution. When a phase depends only on a subset of prior phases (not the immediately preceding one), add YAML frontmatter:
71
+
72
+ ```markdown
73
+ ---
74
+ depends_on: [01-scaffold]
75
+ ---
76
+ # Phase 3: API Endpoints
77
+ ...
78
+ ```
79
+
80
+ **Rules for dependencies:**
81
+
82
+ - Phases without frontmatter automatically depend on the immediately preceding phase (sequential execution).
83
+ - A phase can only depend on phases with a lower index number.
84
+ - If a phase reads or modifies files created by another phase, it must depend on that phase.
85
+ - Phase 01 never has dependencies (it is the root).
86
+ - Use dependencies to enable parallelism when phases work on independent parts of the codebase.
87
+ - When in doubt, omit the frontmatter. False parallelism is worse than false sequentiality.
88
+
89
+ **Example: fan-out pattern**
90
+
91
+ ```text
92
+ 01-scaffold (no deps — root)
93
+ 02-api depends_on: [01-scaffold]
94
+ 03-ui depends_on: [01-scaffold]
95
+ 04-integration depends_on: [02-api, 03-ui]
96
+ ```
97
+
98
+ Phases 02 and 03 run in parallel after 01 completes. Phase 04 waits for both.
99
+
68
100
  ## Rules
69
101
 
70
102
  **No implementation details.** Do not specify creation order, internal structure, sub-agent assignments, implementation patterns, or approach. The builder decides all of this. You describe the destination, not the route.
@@ -0,0 +1,64 @@
1
+ ---
2
+ name: retrospective
3
+ description: Analyzes a completed build to extract learnings, patterns, and recommendations for future builds
4
+ model: opus
5
+ ---
6
+
7
+ You are a build retrospective analyst. After a build completes, you analyze the trajectory, budget, feedback files, and final state to extract actionable learnings.
8
+
9
+ ## Your inputs
10
+
11
+ These are injected into your context:
12
+
13
+ 1. **trajectory.jsonl** — chronological event log of the entire build (plan, build, review, retry events with durations and costs)
14
+ 2. **budget.json** — per-phase, per-role cost breakdown
15
+ 3. **Feedback files** — reviewer verdicts and feedback from any retried phases
16
+ 4. **state.json** — final build state with phase statuses, durations, and retry counts
17
+
18
+ ## Your process
19
+
20
+ ### 1. Analyze the build trajectory
21
+
22
+ - Which phases completed cleanly on the first attempt?
23
+ - Which phases required retries? What were the reviewer's objections?
24
+ - Where was the most time and money spent?
25
+ - Were there any patterns in failures (e.g., the same type of issue recurring)?
26
+
27
+ ### 2. Extract learnings
28
+
29
+ Produce a structured retrospective in the following format. Be specific — name files, patterns, and concrete observations. Avoid generic advice.
30
+
31
+ ```markdown
32
+ ## Build: {build-name} ({date})
33
+
34
+ ### What Worked
35
+ - Specific things that went well (clean passes, efficient phases)
36
+
37
+ ### What Didn't
38
+ - Specific failures, retries, and their root causes
39
+
40
+ ### Patterns to Repeat
41
+ - Concrete patterns worth carrying forward (spec structures, constraint phrasings, phase granularity choices)
42
+
43
+ ### Patterns to Avoid
44
+ - Anti-patterns observed (overly broad phases, missing constraints, spec ambiguities)
45
+
46
+ ### Cost Analysis
47
+ - Total cost and duration
48
+ - Most expensive phases and why
49
+ - Efficiency observations
50
+
51
+ ### Recommendations for Next Build
52
+ - Specific, actionable suggestions for improving spec, constraints, or phase structure
53
+ ```
54
+
55
+ ### 3. Write the output
56
+
57
+ Append your retrospective to the learnings file. Do NOT overwrite previous entries — each build's learnings accumulate.
58
+
59
+ ## Rules
60
+
61
+ - Be concrete and specific, not generic. "Phase 03 failed because the spec didn't mention auth middleware" is useful. "Consider being more specific in specs" is not.
62
+ - Focus on what the build artifacts reveal, not hypotheticals.
63
+ - Keep each section to 3-5 bullet points. Quality over quantity.
64
+ - If the build completed cleanly with no retries, say so — a clean build is still worth noting.
@@ -0,0 +1,21 @@
1
+ import { AssetCatalog, CatalogOptions } from "./types";
2
+ export type CatalogResult = {
3
+ catalog: AssetCatalog;
4
+ stats: {
5
+ total: number;
6
+ added: number;
7
+ updated: number;
8
+ unchanged: number;
9
+ pruned: number;
10
+ classified: number;
11
+ };
12
+ /** Files in auto-describe categories that need vision enrichment. */
13
+ needsVisionDescribe: string[];
14
+ };
15
+ type BuildCatalogOpts = Pick<CatalogOptions, "isForce" | "isClassify" | "model" | "timeout">;
16
+ /**
17
+ * Build or update the asset catalog.
18
+ * Handles all media types. Vision enrichment and sprite packing are handled separately.
19
+ */
20
+ export declare const buildCatalog: (assetDir: string, buildDir: string, opts: BuildCatalogOpts) => Promise<CatalogResult>;
21
+ export {};
@@ -0,0 +1,305 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.buildCatalog = void 0;
37
+ const fs = __importStar(require("node:fs"));
38
+ const path = __importStar(require("node:path"));
39
+ const parse_conventions_1 = require("./parse-conventions");
40
+ const extract_metadata_1 = require("./extract-metadata");
41
+ const classify_1 = require("./classify");
42
+ /** Map file extensions to media types. */
43
+ const MEDIA_EXTENSIONS = {
44
+ // images
45
+ ".png": "image", ".jpg": "image", ".jpeg": "image",
46
+ ".gif": "image", ".webp": "image", ".svg": "image", ".avif": "image",
47
+ // audio
48
+ ".mp3": "audio", ".wav": "audio", ".ogg": "audio",
49
+ ".flac": "audio", ".aac": "audio", ".m4a": "audio",
50
+ // video
51
+ ".mp4": "video", ".webm": "video", ".mov": "video", ".avi": "video",
52
+ // text
53
+ ".txt": "text", ".json": "text", ".csv": "text",
54
+ ".md": "text", ".yaml": "text", ".yml": "text",
55
+ };
56
+ /** Detect media type from file extension. */
57
+ const detectMediaType = (filePath) => MEDIA_EXTENSIONS[path.extname(filePath).toLowerCase()] ?? null;
58
+ /** Recursively walk a directory tree and return all asset file paths (relative to root). */
59
+ const walkAssets = (dir, root) => {
60
+ const base = root ?? dir;
61
+ const results = [];
62
+ for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
63
+ const fullPath = path.join(dir, entry.name);
64
+ if (entry.isDirectory()) {
65
+ results.push(...walkAssets(fullPath, base));
66
+ }
67
+ else if (detectMediaType(entry.name) !== null) {
68
+ results.push(path.relative(base, fullPath));
69
+ }
70
+ }
71
+ return results;
72
+ };
73
+ /** Load existing catalog from disk, if present. */
74
+ const loadExistingCatalog = (catalogPath) => {
75
+ if (!fs.existsSync(catalogPath))
76
+ return null;
77
+ try {
78
+ return JSON.parse(fs.readFileSync(catalogPath, "utf-8"));
79
+ }
80
+ catch {
81
+ return null;
82
+ }
83
+ };
84
+ /** Build a lookup map from an existing catalog for incremental updates. */
85
+ const buildHashIndex = (catalog) => {
86
+ const index = new Map();
87
+ if (!catalog)
88
+ return index;
89
+ for (const entry of catalog.assets) {
90
+ index.set(entry.file, entry);
91
+ }
92
+ return index;
93
+ };
94
+ /** Detect the most common resolution among square or nearly-square image assets. */
95
+ const detectResolution = (assets) => {
96
+ const sizes = new Map();
97
+ for (const a of assets) {
98
+ if (a.mediaType !== "image")
99
+ continue;
100
+ if (a.isSpritesheet && a.frameSize) {
101
+ const key = `${a.frameSize.w}x${a.frameSize.h}`;
102
+ sizes.set(key, (sizes.get(key) ?? 0) + 1);
103
+ }
104
+ else if (a.width && a.height && a.width === a.height && a.width <= 256) {
105
+ const key = `${a.width}x${a.height}`;
106
+ sizes.set(key, (sizes.get(key) ?? 0) + 1);
107
+ }
108
+ }
109
+ if (sizes.size === 0)
110
+ return null;
111
+ return [...sizes.entries()].sort((a, b) => b[1] - a[1])[0][0];
112
+ };
113
+ /** Build aggregate palette from all image assets (top 8 most frequent colours). */
114
+ const detectPalette = (assets) => {
115
+ const freq = new Map();
116
+ for (const a of assets) {
117
+ if (!a.palette)
118
+ continue;
119
+ for (const c of a.palette) {
120
+ freq.set(c, (freq.get(c) ?? 0) + 1);
121
+ }
122
+ }
123
+ return [...freq.entries()]
124
+ .sort((a, b) => b[1] - a[1])
125
+ .slice(0, 8)
126
+ .map(([colour]) => colour);
127
+ };
128
+ /** Detect visual style from image asset properties. */
129
+ const detectStyle = (assets) => {
130
+ const imageAssets = assets.filter((a) => a.mediaType === "image");
131
+ if (imageAssets.length === 0)
132
+ return null;
133
+ const smallAssets = imageAssets.filter((a) => {
134
+ const size = a.isSpritesheet && a.frameSize
135
+ ? Math.max(a.frameSize.w, a.frameSize.h)
136
+ : Math.max(a.width ?? 0, a.height ?? 0);
137
+ return size <= 128;
138
+ });
139
+ if (smallAssets.length > imageAssets.length * 0.6)
140
+ return "pixel-art";
141
+ const svgCount = imageAssets.filter((a) => a.format === "svg").length;
142
+ if (svgCount > imageAssets.length * 0.5)
143
+ return "vector";
144
+ return null;
145
+ };
146
+ /** Derive aggregate visual identity from all cataloged assets. */
147
+ const deriveVisualIdentity = (assets) => {
148
+ const style = detectStyle(assets);
149
+ return {
150
+ detectedStyle: style,
151
+ detectedPalette: detectPalette(assets),
152
+ detectedResolution: detectResolution(assets),
153
+ detectedScaling: style === "pixel-art" ? "nearest" : null,
154
+ };
155
+ };
156
+ /** Compare detected palette against design.md palette and produce warnings. */
157
+ const checkPaletteMismatches = (assets, buildDir, ridgelineDir) => {
158
+ const warnings = [];
159
+ const designPaths = [
160
+ path.join(buildDir, "design.md"),
161
+ path.join(ridgelineDir, "design.md"),
162
+ ];
163
+ let designContent = null;
164
+ for (const p of designPaths) {
165
+ if (fs.existsSync(p)) {
166
+ designContent = fs.readFileSync(p, "utf-8");
167
+ break;
168
+ }
169
+ }
170
+ if (!designContent)
171
+ return warnings;
172
+ const hexPattern = /#[0-9a-fA-F]{6}/g;
173
+ const designColours = new Set([...designContent.matchAll(hexPattern)].map((m) => m[0].toLowerCase()));
174
+ if (designColours.size === 0)
175
+ return warnings;
176
+ for (const asset of assets) {
177
+ if (!asset.palette)
178
+ continue;
179
+ const offPalette = asset.palette.filter((c) => !designColours.has(c.toLowerCase()));
180
+ if (offPalette.length > 0) {
181
+ warnings.push(`${asset.file} uses colours (${offPalette.join(", ")}) not found in design.md palette. This may be intentional.`);
182
+ }
183
+ }
184
+ return warnings;
185
+ };
186
+ /**
187
+ * Build or update the asset catalog.
188
+ * Handles all media types. Vision enrichment and sprite packing are handled separately.
189
+ */
190
+ const buildCatalog = async (assetDir, buildDir, opts) => {
191
+ const ridgelineDir = path.join(process.cwd(), ".ridgeline");
192
+ const catalogPath = path.join(buildDir, "asset-catalog.json");
193
+ const existing = loadExistingCatalog(catalogPath);
194
+ const hashIndex = buildHashIndex(existing);
195
+ const assetFiles = walkAssets(assetDir);
196
+ const existingFiles = new Set(hashIndex.keys());
197
+ const assets = [];
198
+ const needsVisionDescribe = [];
199
+ let added = 0;
200
+ let updated = 0;
201
+ let unchanged = 0;
202
+ let classified = 0;
203
+ const timeoutMs = opts.timeout * 60 * 1000;
204
+ const totalFiles = assetFiles.length;
205
+ let processedCount = 0;
206
+ for (const relPath of assetFiles) {
207
+ const absPath = path.join(assetDir, relPath);
208
+ const hash = (0, extract_metadata_1.computeContentHash)(absPath);
209
+ const prev = hashIndex.get(relPath);
210
+ existingFiles.delete(relPath);
211
+ // Skip unchanged files (unless --force)
212
+ if (!opts.isForce && prev && prev.hash === hash) {
213
+ assets.push(prev);
214
+ unchanged++;
215
+ // Still track if auto-describe category needs vision
216
+ if (prev.mediaType === "image") {
217
+ const conv = (0, parse_conventions_1.parseConventions)(relPath);
218
+ if (parse_conventions_1.AUTO_DESCRIBE_CATEGORIES.has(conv.category) && !prev.description) {
219
+ needsVisionDescribe.push(relPath);
220
+ }
221
+ }
222
+ continue;
223
+ }
224
+ processedCount++;
225
+ const mediaType = detectMediaType(relPath);
226
+ const conventions = (0, parse_conventions_1.parseConventions)(relPath);
227
+ const basic = (0, extract_metadata_1.extractBasicMetadata)(absPath);
228
+ // Build the entry — image-specific metadata only for images
229
+ const entry = {
230
+ file: relPath,
231
+ hash,
232
+ mediaType,
233
+ category: conventions.category,
234
+ name: conventions.name,
235
+ subject: conventions.subject,
236
+ state: conventions.state,
237
+ fileSizeBytes: basic.fileSizeBytes,
238
+ extension: basic.extension,
239
+ };
240
+ if (mediaType === "image") {
241
+ const meta = await (0, extract_metadata_1.extractImageMetadata)(absPath);
242
+ const palette = await (0, extract_metadata_1.extractPalette)(absPath);
243
+ const spritesheet = (0, extract_metadata_1.detectSpritesheet)(meta.width, meta.height);
244
+ const isTileable = await (0, extract_metadata_1.detectTileable)(absPath, meta.width, meta.height);
245
+ const defaults = (0, parse_conventions_1.inferDefaults)(conventions.category);
246
+ entry.width = meta.width;
247
+ entry.height = meta.height;
248
+ entry.format = meta.format;
249
+ entry.hasAlpha = meta.hasAlpha;
250
+ entry.channels = meta.channels;
251
+ entry.dominantColour = palette.dominantColour;
252
+ entry.palette = palette.palette;
253
+ entry.isSpritesheet = spritesheet.isSpritesheet;
254
+ entry.frameCount = spritesheet.frameCount;
255
+ entry.frameSize = spritesheet.frameSize;
256
+ entry.frameDirection = spritesheet.frameDirection;
257
+ entry.suggestedAnchor = defaults.anchor;
258
+ entry.suggestedZLayer = defaults.zLayer;
259
+ entry.isTileable = isTileable;
260
+ }
261
+ // Classify uncategorized files when --classify is set
262
+ if (conventions.category === "uncategorized" && opts.isClassify) {
263
+ process.stderr.write(`\x1b[90m Classifying ${relPath} (${processedCount}/${totalFiles})...\x1b[0m\n`);
264
+ const result = (0, classify_1.classifyByHeuristics)(relPath, basic.extension, mediaType)
265
+ ?? (0, classify_1.classifyWithAI)(absPath, relPath, basic.extension, mediaType, opts.model, timeoutMs);
266
+ entry.category = result.category;
267
+ entry.isClassified = true;
268
+ entry.classificationConfidence = result.confidence;
269
+ classified++;
270
+ // Update anchor/zLayer defaults based on new category
271
+ if (mediaType === "image") {
272
+ const defaults = (0, parse_conventions_1.inferDefaults)(entry.category);
273
+ entry.suggestedAnchor = defaults.anchor;
274
+ entry.suggestedZLayer = defaults.zLayer;
275
+ }
276
+ }
277
+ assets.push(entry);
278
+ if (mediaType === "image" && parse_conventions_1.AUTO_DESCRIBE_CATEGORIES.has(entry.category)) {
279
+ needsVisionDescribe.push(relPath);
280
+ }
281
+ if (prev) {
282
+ updated++;
283
+ }
284
+ else {
285
+ added++;
286
+ }
287
+ }
288
+ // Remaining entries in existingFiles are pruned (files removed from disk)
289
+ const pruned = existingFiles.size;
290
+ const catalog = {
291
+ generatedAt: new Date().toISOString(),
292
+ assetDir,
293
+ isDescribed: existing?.isDescribed ?? false,
294
+ visualIdentity: deriveVisualIdentity(assets),
295
+ warnings: checkPaletteMismatches(assets, buildDir, ridgelineDir),
296
+ assets,
297
+ };
298
+ return {
299
+ catalog,
300
+ stats: { total: assets.length, added, updated, unchanged, pruned, classified },
301
+ needsVisionDescribe,
302
+ };
303
+ };
304
+ exports.buildCatalog = buildCatalog;
305
+ //# sourceMappingURL=build-catalog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-catalog.js","sourceRoot":"","sources":["../../src/catalog/build-catalog.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import { MediaType } from "./types";
2
+ type ClassificationResult = {
3
+ category: string;
4
+ confidence: "high" | "medium" | "low";
5
+ };
6
+ /**
7
+ * Attempt to classify a file using filename pattern matching.
8
+ * Returns null if no heuristic matches confidently.
9
+ */
10
+ export declare const classifyByHeuristics: (filename: string, ext: string, mediaType: MediaType) => ClassificationResult | null;
11
+ /**
12
+ * Classify a single file using AI.
13
+ * Dispatches to vision (images) or text-only (audio/video/text).
14
+ */
15
+ export declare const classifyWithAI: (absPath: string, filename: string, ext: string, mediaType: MediaType, model: string, timeoutMs: number) => ClassificationResult;
16
+ export {};