Skip to content

Add project language icons - #39

Merged
Jay1 merged 11 commits into
mainfrom
jcode/project-language-icons
Jun 1, 2026
Merged

Add project language icons#39
Jay1 merged 11 commits into
mainfrom
jcode/project-language-icons

Conversation

@Jay1

@Jay1 Jay1 commented Jun 1, 2026

Copy link
Copy Markdown
Owner

Summary

  • add project icon metadata to orchestration contracts and projections
  • detect TypeScript/Vue project icons with bounded server-side root checks
  • persist and backfill icon metadata, then render sidebar/search/project-picker icons in the web UI

Verification

  • bun run --cwd packages/contracts test src/orchestration.test.ts
  • bun run --cwd apps/server test src/project/Layers/ProjectLanguageIconResolver.test.ts src/persistence/Layers/ProjectionRepositories.test.ts src/orchestration/decider.projectScripts.test.ts src/orchestration/Layers/ProjectionPipeline.test.ts src/orchestration/Layers/ProjectionSnapshotQuery.test.ts src/orchestration/Layers/OrchestrationEngine.test.ts
  • bun run --cwd apps/web test src/components/ProjectSidebarIcon.test.tsx src/components/SidebarSearchPalette.logic.test.ts src/components/Sidebar.logic.test.ts src/store.test.ts src/focusedChatContext.test.ts
  • bun run --cwd apps/web test:browser -- src/components/ProjectSidebarIcon.browser.tsx
  • bun run --cwd packages/contracts typecheck
  • bun run --cwd apps/server typecheck
  • bun run --cwd apps/web typecheck
  • git diff --check

Summary by CodeRabbit

  • New Features
    • Added language and framework icons for projects (TypeScript, Vue) displayed in the sidebar and search palette
    • Icons are automatically detected based on project configuration files
    • Projects without detected frameworks display a folder icon with favicon fallback

@coderabbitai

coderabbitai Bot commented Jun 1, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@Jay1, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 5 minutes and 17 seconds. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0c1ff849-c60b-4c94-bee9-9f250086385d

📥 Commits

Reviewing files that changed from the base of the PR and between 485a8e1 and e920318.

📒 Files selected for processing (7)
  • apps/server/src/orchestration/Layers/OrchestrationEngine.test.ts
  • apps/server/src/orchestration/Layers/OrchestrationEngine.ts
  • apps/web/src/components/Sidebar.logic.test.ts
  • apps/web/src/components/Sidebar.tsx
  • apps/web/src/store.test.ts
  • apps/web/src/store.ts
  • docs/superpowers/plans/2026-06-01-project-language-icons.md
📝 Walkthrough

Walkthrough

Adds project language/framework icon support across the full stack. New contract schemas define icon metadata keyed by language ID. A filesystem-based resolver detects Vue and TypeScript projects. Icons persist in the projection layer via schema migration. Orchestration engine schedules icon detection on project creation and performs once-per-process backfill. Web UI renders language glyphs in sidebars when metadata is present, otherwise falls back to folder + favicon.

Changes

Project Language Icons

Layer / File(s) Summary
Contract schemas for project icons
packages/contracts/src/orchestration.ts, packages/contracts/src/orchestration.test.ts
New ProjectIconId and ProjectIconMetadata schemas; commands/payloads extended to carry iconMetadata; OrchestrationProject and shells include nullable iconMetadata field.
Icon resolver service
apps/server/src/project/Services/ProjectLanguageIconResolver.ts, apps/server/src/project/Layers/ProjectLanguageIconResolver.ts, apps/server/src/project/Layers/ProjectLanguageIconResolver.test.ts
Service interface and Effect-based implementation; detects Vue from package.json dependencies (preferred), TypeScript from tsconfig.json, returns null otherwise; tests verify marker detection and non-recursive scoping.
Persistence layer: schema and migration
apps/server/src/persistence/Services/ProjectionProjects.ts, apps/server/src/persistence/Migrations/038_ProjectionProjectsIconMetadata.ts, apps/server/src/persistence/Migrations.ts, apps/server/src/persistence/Layers/ProjectionProjects.ts
Adds iconMetadata field to projection schema; idempotent migration adds icon_metadata_json TEXT column; repository upsert/queries select and persist metadata.
Orchestration command handling
apps/server/src/orchestration/decider.ts, apps/server/src/orchestration/decider.projectScripts.test.ts, apps/server/src/orchestration/projector.ts, apps/server/src/orchestration/projectMetadataProjection.ts
Command decider emits iconMetadata in events; projector and projection propagate metadata through read model; tests verify event payloads include metadata.
Orchestration snapshot and queries
apps/server/src/orchestration/Layers/ProjectionSnapshotQuery.ts, apps/server/src/orchestration/Layers/ProjectionSnapshotQuery.test.ts
SQL selects icon_metadata_json AS "iconMetadata" for all project queries; snapshot hydration includes metadata in projected shells and full models.
Orchestration engine: icon detection scheduling
apps/server/src/orchestration/Layers/OrchestrationEngine.ts
Injects ProjectLanguageIconResolver; adds sequential scope for background scheduling; detects missing icon metadata on startup (backfill) and on-the-fly for new project.created events; enqueues project.meta.update commands non-blockingly.
Orchestration infrastructure and test wiring
apps/server/src/orchestration/runtimeLayer.ts, apps/server/integration/OrchestrationEngineHarness.integration.ts, apps/server/src/orchestration/Layers/CheckpointReactor.test.ts, apps/server/src/orchestration/Layers/OrchestrationEngine.test.ts, apps/server/src/orchestration/Layers/ProjectionPipeline.test.ts, apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts, apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.test.ts
Wires ProjectLanguageIconResolverLive into OrchestrationInfrastructureLayerLive; provides no-op resolver in test harnesses; adds integration and unit tests for icon detection and backfill behavior.
Web component: icon rendering
apps/web/src/components/ProjectSidebarIcon.tsx, apps/web/src/components/ProjectSidebarIcon.test.tsx, apps/web/src/components/ProjectSidebarIcon.browser.tsx
Dual render mode: text glyph with aria-label and role="img" when iconMetadata present; folder + favicon when null. Props extended with iconMetadata and className. Favicon probing disabled when metadata set.
Web component wiring: Sidebar and palette
apps/web/src/components/Sidebar.tsx, apps/web/src/components/SidebarSearchPalette.logic.ts, apps/web/src/components/SidebarSearchPalette.logic.test.ts, apps/web/src/components/SidebarSearchPalette.tsx, apps/web/src/components/chat/ProjectPicker.tsx
Sidebar and palette components pass project.iconMetadata to ProjectSidebarIcon; SidebarSearchProject interface extended with iconMetadata; ProjectPicker renders project icons via ProjectSidebarIcon instead of generic folder.
Web state management: normalization and events
apps/web/src/types.ts, apps/web/src/store.ts, apps/web/src/store.test.ts, apps/web/src/focusedChatContext.test.ts, apps/web/src/components/Sidebar.logic.test.ts
Project type includes iconMetadata: ProjectIconMetadata | null. Store normalization preserves and deep-equality-checks metadata across read-model sync and shell snapshots. Event handlers for project.created and project.meta-updated upsert metadata; conditional preservation on partial updates.
Implementation plan documentation
docs/superpowers/plans/2026-06-01-project-language-icons.md
Plan document specifying acceptance criteria, persistence/migration/detection/orchestration behavior, and QA checklist.

🎯 4 (Complex) | ⏱️ ~60 minutes

Suggested labels

vouch:trusted, size:XL

Poem

🐰 With icons dancing in the fold,
Vue and TypeScript stories told,
Filesystem whispers guide the way,
While glyphs now brighten every day!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Add project language icons' clearly and concisely summarizes the main change—adding project language/framework icon support to the system.
Description check ✅ Passed The PR description covers the summary, verification steps (comprehensive test commands), and key changes, though it lacks some template sections like 'Why', 'UI Changes', and 'Reviewer Notes'.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch jcode/project-language-icons

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions Bot added size:L vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. labels Jun 1, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
docs/superpowers/plans/2026-06-01-project-language-icons.md (1)

63-63: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Remove accidental trailing token from the document.

Line 63 contains a bare 63, which appears to be an editing artifact and should be deleted.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/superpowers/plans/2026-06-01-project-language-icons.md` at line 63,
Remove the accidental trailing token "63" from the document (the bare numeric
artifact currently present on line 63); edit the markdown file to delete that
lone token so the document contains only intended content and then save the file
(no code changes required).
🧹 Nitpick comments (2)
docs/superpowers/plans/2026-06-01-project-language-icons.md (1)

1-63: ⚡ Quick win

Add the required document metadata table for this new plan doc.

This new document should include/update its metadata table (owner/status/last-updated or repo-standard fields) to comply with docs conventions.

As per coding guidelines, "Keep metadata tables current when adding or substantially changing a document."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/superpowers/plans/2026-06-01-project-language-icons.md` around lines 1 -
63, Add a repo-standard metadata table to the top of the new plan document so it
includes owner, status, and last-updated (and any other repo-required fields) to
satisfy docs conventions; update the file "Project Language Icons Implementation
Plan" by inserting or updating the YAML/Markdown metadata block (owner, status,
last-updated) at the document head, ensure values are accurate (set owner to the
responsible team/person, status to draft/in-progress/etc., and last-updated to
today’s date), and keep the format consistent with other plan docs in the repo
so tooling and reviewers pick it up.
apps/server/src/project/Layers/ProjectLanguageIconResolver.test.ts (1)

43-58: 💤 Low value

Optional: broaden Vue/parse coverage.

packageHasDependency also checks devDependencies/peerDependencies, and readRootPackageJson swallows malformed JSON to null — none of these branches are exercised. Consider adding cases for a devDependencies.vue project and a malformed package.json (expecting tsconfig fallback or null).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/server/src/project/Layers/ProjectLanguageIconResolver.test.ts` around
lines 43 - 58, Add unit tests for ProjectLanguageIconResolver to exercise
packageHasDependency and readRootPackageJson branches: create tests that (1)
place "vue" in devDependencies and (2) in peerDependencies and assert
resolveMetadata(cwd) still returns { iconId: "vue", label: "Vue" when
tsconfig.json exists; and (3) create a malformed package.json (invalid JSON) and
assert resolveMetadata(cwd) follows the documented fallback (either returns
based on tsconfig.json or null per current implementation). Reference
ProjectLanguageIconResolver.resolveMetadata, packageHasDependency and
readRootPackageJson when adding these cases so the resolver’s handling of
dev/peer deps and malformed package.json is covered.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/server/src/orchestration/Layers/OrchestrationEngine.test.ts`:
- Around line 168-179: The polling loop that repeatedly calls
engine.getReadModel (checking project via asProjectId("project-icon-create"))
only spins 20×10ms (~200ms) which is too short and causes CI flakes; replace
this tight spin with a longer timeout or the existing longer wait-helper
pattern: either increase attempts and sleep (e.g., attempts 50 with
Effect.sleep("100 millis") for ~5s) or call the shared wait-for helper used
elsewhere, and apply the same change to the other similar loop (the second
polling block that also uses engine.getReadModel/asProjectId).

In `@apps/server/src/orchestration/Layers/OrchestrationEngine.ts`:
- Around line 188-189: The scheduled icon backfill is being forked inside
scheduleProjectIconMetadataDetection so Effect.forEach(..., { concurrency: 1 })
only serializes fiber creation rather than the work; change
scheduleProjectIconMetadataDetection to return a plain Effect (do not fork
inside it) and move the fork (Effect.forkIn / .fork) to the post-project.created
call site where the helper is invoked (or alternatively protect the body with a
semaphore) so that the forEach with concurrency: 1 actually serializes the
detection/update work; update references to projectIconDetectionScope and any
callers that currently expect a forked effect accordingly.
- Around line 168-177: The scheduled project.meta.update is enqueued based on a
snapshot and can overwrite newer iconMetadata; modify the scheduling to include
a runtime guard so the actual update only runs if iconMetadata is still missing
at execution time: when calling enqueueInternalCommand (the command with type
"project.meta.update" and CommandId.makeUnsafe(...)), include either an explicit
precondition flag/expected state (e.g., expectedIconMissing: true or
expectedIconMetadata: null) or change the handler for "project.meta.update" to
check current project.iconMetadata and skip applying the iconMetadata if it's no
longer null; ensure this check happens in the command execution path (not only
before enqueueing) so stale detections won't overwrite newer data.

In `@apps/web/src/store.ts`:
- Around line 598-602: The current logic in normalizeProjectFromReadModel and
normalizeProjectFromShell unconditionally treats incoming.iconMetadata as
nullable and may overwrite an existing non-null previous.iconMetadata with a
stale snapshot; change the assignment so you only replace previous.iconMetadata
when the incoming snapshot is fresh (e.g., compare incoming.updatedAt >
previous.updatedAt) or when previous.iconMetadata is null/undefined — i.e., if
previous?.iconMetadata is non-null and previous.updatedAt is newer than
incoming.updatedAt, keep previous.iconMetadata, otherwise use
incoming.iconMetadata (still defaulting to null if absent).

In `@docs/superpowers/plans/2026-06-01-project-language-icons.md`:
- Line 24: Change the event name used in the plan from project.meta.update to
the canonical project.meta-updated so it matches the rest of the document and
the feature summary; search for occurrences of project.meta.update (e.g., the
mention near the decider event) and replace them with project.meta-updated to
keep a single canonical event name throughout the plan and related docs.

---

Outside diff comments:
In `@docs/superpowers/plans/2026-06-01-project-language-icons.md`:
- Line 63: Remove the accidental trailing token "63" from the document (the bare
numeric artifact currently present on line 63); edit the markdown file to delete
that lone token so the document contains only intended content and then save the
file (no code changes required).

---

Nitpick comments:
In `@apps/server/src/project/Layers/ProjectLanguageIconResolver.test.ts`:
- Around line 43-58: Add unit tests for ProjectLanguageIconResolver to exercise
packageHasDependency and readRootPackageJson branches: create tests that (1)
place "vue" in devDependencies and (2) in peerDependencies and assert
resolveMetadata(cwd) still returns { iconId: "vue", label: "Vue" when
tsconfig.json exists; and (3) create a malformed package.json (invalid JSON) and
assert resolveMetadata(cwd) follows the documented fallback (either returns
based on tsconfig.json or null per current implementation). Reference
ProjectLanguageIconResolver.resolveMetadata, packageHasDependency and
readRootPackageJson when adding these cases so the resolver’s handling of
dev/peer deps and malformed package.json is covered.

In `@docs/superpowers/plans/2026-06-01-project-language-icons.md`:
- Around line 1-63: Add a repo-standard metadata table to the top of the new
plan document so it includes owner, status, and last-updated (and any other
repo-required fields) to satisfy docs conventions; update the file "Project
Language Icons Implementation Plan" by inserting or updating the YAML/Markdown
metadata block (owner, status, last-updated) at the document head, ensure values
are accurate (set owner to the responsible team/person, status to
draft/in-progress/etc., and last-updated to today’s date), and keep the format
consistent with other plan docs in the repo so tooling and reviewers pick it up.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 8899b5eb-1479-4bf2-9e28-db6cbee50ec0

📥 Commits

Reviewing files that changed from the base of the PR and between 786e377 and 485a8e1.

📒 Files selected for processing (37)
  • apps/server/integration/OrchestrationEngineHarness.integration.ts
  • apps/server/src/orchestration/Layers/CheckpointReactor.test.ts
  • apps/server/src/orchestration/Layers/OrchestrationEngine.test.ts
  • apps/server/src/orchestration/Layers/OrchestrationEngine.ts
  • apps/server/src/orchestration/Layers/ProjectionPipeline.test.ts
  • apps/server/src/orchestration/Layers/ProjectionSnapshotQuery.test.ts
  • apps/server/src/orchestration/Layers/ProjectionSnapshotQuery.ts
  • apps/server/src/orchestration/Layers/ProviderCommandReactor.test.ts
  • apps/server/src/orchestration/Layers/ProviderRuntimeIngestion.test.ts
  • apps/server/src/orchestration/decider.projectScripts.test.ts
  • apps/server/src/orchestration/decider.ts
  • apps/server/src/orchestration/projectMetadataProjection.ts
  • apps/server/src/orchestration/projector.ts
  • apps/server/src/orchestration/runtimeLayer.ts
  • apps/server/src/persistence/Layers/ProjectionProjects.ts
  • apps/server/src/persistence/Migrations.ts
  • apps/server/src/persistence/Migrations/038_ProjectionProjectsIconMetadata.ts
  • apps/server/src/persistence/Services/ProjectionProjects.ts
  • apps/server/src/project/Layers/ProjectLanguageIconResolver.test.ts
  • apps/server/src/project/Layers/ProjectLanguageIconResolver.ts
  • apps/server/src/project/Services/ProjectLanguageIconResolver.ts
  • apps/web/src/components/ProjectSidebarIcon.browser.tsx
  • apps/web/src/components/ProjectSidebarIcon.test.tsx
  • apps/web/src/components/ProjectSidebarIcon.tsx
  • apps/web/src/components/Sidebar.logic.test.ts
  • apps/web/src/components/Sidebar.tsx
  • apps/web/src/components/SidebarSearchPalette.logic.test.ts
  • apps/web/src/components/SidebarSearchPalette.logic.ts
  • apps/web/src/components/SidebarSearchPalette.tsx
  • apps/web/src/components/chat/ProjectPicker.tsx
  • apps/web/src/focusedChatContext.test.ts
  • apps/web/src/store.test.ts
  • apps/web/src/store.ts
  • apps/web/src/types.ts
  • docs/superpowers/plans/2026-06-01-project-language-icons.md
  • packages/contracts/src/orchestration.test.ts
  • packages/contracts/src/orchestration.ts

Comment thread apps/server/src/orchestration/Layers/OrchestrationEngine.test.ts Outdated
Comment thread apps/server/src/orchestration/Layers/OrchestrationEngine.ts Outdated
Comment thread apps/server/src/orchestration/Layers/OrchestrationEngine.ts Outdated
Comment thread apps/web/src/store.ts Outdated
Comment thread docs/superpowers/plans/2026-06-01-project-language-icons.md Outdated
@github-actions github-actions Bot added size:XL and removed size:L labels Jun 1, 2026
@Jay1 Jay1 self-assigned this Jun 1, 2026
@Jay1
Jay1 merged commit a83f263 into main Jun 1, 2026
8 checks passed
@Jay1
Jay1 deleted the jcode/project-language-icons branch June 1, 2026 16:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XL vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant