Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ Last updated: 2026-03-11
- GitHub-facing setup is staged: no-git -> local-git -> GitHub-connected -> protected-branches with required checks.
- Shared contracts live in `packages/shared-types` so the UI can evolve without importing Python internals.
- Shared contracts should ultimately model section, role, cue, confidence, and export artifacts explicitly enough that desktop UI and analysis outputs do not invent their own parallel schemas.
- The current shared-types baseline includes a rehearsal-domain fixture that exercises section, role, cue, confidence, provenance, and export-summary fields in the desktop shell before the full analysis pipeline lands.
- Product and UX decisions should prefer rehearsal-first simplicity while still maintaining high analytical accuracy.
- Security decisions should prefer allowlisted narrow capabilities over generic convenience APIs.

Expand Down
2 changes: 1 addition & 1 deletion apps/desktop/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"build": "vite build",
"lint": "eslint \"src/**/*.{ts,tsx}\" vite.config.ts",
"typecheck": "tsc --noEmit",
"test": "vitest run --coverage"
"test": "node -e \"require('node:fs').mkdirSync('coverage/.tmp', { recursive: true })\" && vitest run --coverage"
},
"dependencies": {
"@bandscope/shared-types": "0.1.0",
Expand Down
10 changes: 9 additions & 1 deletion apps/desktop/src/App.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,19 @@ import { render, screen } from "@testing-library/react";
import { App } from "./App";

describe("App", () => {
it("shows the harness status and supported formats", () => {
it("shows the shared rehearsal overview", () => {
render(<App />);

expect(screen.getByRole("heading", { name: /BandScope Bootstrap/i })).toBeInTheDocument();
expect(screen.getByText(/wav, mp3, flac, m4a/i)).toBeInTheDocument();
expect(screen.getByRole("heading", { name: /Late Night Set/i })).toBeInTheDocument();
expect(screen.getByRole("heading", { name: /Verse 1/i })).toBeInTheDocument();
expect(screen.getByText(/Bass Guitar/i)).toBeInTheDocument();
expect(screen.getByText(/Keyboard 1 Right Hand/i)).toBeInTheDocument();
expect(screen.getByText(/Lead Vocal/i)).toBeInTheDocument();
expect(screen.getByText(/Section confidence: Needs ear check \(Auto-detected\)/i)).toBeInTheDocument();
expect(screen.getAllByText(/harmony source: Auto-detected/i)).toHaveLength(3);
expect(screen.getByText(/manual override: C#m11 \(User-confirmed\)/i)).toBeInTheDocument();
expect(screen.getByText(/Home baseline is wired/i)).toBeInTheDocument();
});
});
46 changes: 45 additions & 1 deletion apps/desktop/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { SUPPORTED_AUDIO_FORMATS } from "@bandscope/shared-types";
import { useMemo } from "react";
import {
createDemoRehearsalSong,
SUPPORTED_AUDIO_FORMATS
} from "@bandscope/shared-types";
import { ChordsFeature } from "./features/chords";
import { HomeFeature } from "./features/home";
import { PlayerFeature } from "./features/player";
Expand All @@ -8,6 +12,16 @@ import { createTranslator, detectPreferredLocale } from "./i18n";

export function App() {
const t = createTranslator(detectPreferredLocale());
const rehearsalSong = useMemo(() => createDemoRehearsalSong(), []);
const confidenceLabels = {
low: t("confidenceLevelLow"),
medium: t("confidenceLevelMedium"),
high: t("confidenceLevelHigh")
} as const;
const provenanceLabels = {
model: t("provenanceSourceModel"),
user: t("provenanceSourceUser")
} as const;

return (
<main>
Expand All @@ -16,6 +30,36 @@ export function App() {
<p>
{t("supportedFormats")}: {SUPPORTED_AUDIO_FORMATS.join(", ")}
</p>
<section>
<h2>{rehearsalSong.title}</h2>
<p>{rehearsalSong.exportSummary.headline}</p>
</section>
{rehearsalSong.sections.map((section) => (
<section key={section.id}>
<h3>{section.label}</h3>
<p>{section.groove}</p>
<p>
{t("sectionConfidence")}: {confidenceLabels[section.confidence.level]} ({provenanceLabels[section.confidence.source]})
</p>
<ul>
{section.roles.map((role) => (
<li key={role.id}>
<strong>{role.name}</strong>
<span> - {role.harmony.chord}</span>
<span> - {role.cue.value}</span>
<span> - {t("roleConfidence")}: {confidenceLabels[role.confidence.level]}</span>
<span> - {t("harmonySource")}: {provenanceLabels[role.harmony.source]}</span>
{role.manualOverrides.map((override, index) => (
<span key={`${override.field}-${override.source}-${override.value.chord}-${index}`}>
{" "}
- {t("manualOverride")}: {override.value.chord} ({provenanceLabels[override.source]})
</span>
))}
</li>
))}
</ul>
</section>
))}
<HomeFeature title={t("homeCard")} />
<PlayerFeature title={t("playerCard")} />
<ChordsFeature title={t("chordsCard")} />
Expand Down
11 changes: 10 additions & 1 deletion apps/desktop/src/locales/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,14 @@
"chordsCard": "Chord analysis baseline is wired.",
"rangesCard": "Range analysis baseline is wired.",
"settingsCard": "Settings baseline is wired.",
"supportedFormats": "Supported input formats"
"supportedFormats": "Supported input formats",
"sectionConfidence": "Section confidence",
"roleConfidence": "confidence",
"harmonySource": "harmony source",
"manualOverride": "manual override",
"confidenceLevelLow": "Low confidence",
"confidenceLevelMedium": "Needs ear check",
"confidenceLevelHigh": "Ready to trust",
"provenanceSourceModel": "Auto-detected",
"provenanceSourceUser": "User-confirmed"
}
11 changes: 10 additions & 1 deletion apps/desktop/src/locales/ko/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,14 @@
"chordsCard": "์ฝ”๋“œ ๋ถ„์„ ๊ธฐ์ค€์„ ์ด ์—ฐ๊ฒฐ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.",
"rangesCard": "์Œ์—ญ ๋ถ„์„ ๊ธฐ์ค€์„ ์ด ์—ฐ๊ฒฐ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.",
"settingsCard": "์„ค์ • ๊ธฐ์ค€์„ ์ด ์—ฐ๊ฒฐ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.",
"supportedFormats": "์ง€์› ์ž…๋ ฅ ํ˜•์‹"
"supportedFormats": "์ง€์› ์ž…๋ ฅ ํ˜•์‹",
"sectionConfidence": "๊ตฌ๊ฐ„ ์‹ ๋ขฐ๋„",
"roleConfidence": "์‹ ๋ขฐ๋„",
"harmonySource": "ํ™”์„ฑ ์ถœ์ฒ˜",
"manualOverride": "์ˆ˜๋™ ์ˆ˜์ •",
"confidenceLevelLow": "ํ™•์‹ ์ด ๋‚ฎ์Œ",
"confidenceLevelMedium": "๊ท€๋กœ ํ•œ ๋ฒˆ ๋” ํ™•์ธ",
"confidenceLevelHigh": "๋ฏฟ๊ณ  ๊ฐ€์ ธ๊ฐ€๋„ ๋จ",
"provenanceSourceModel": "์ž๋™ ์ถ”์ •",
"provenanceSourceUser": "์‚ฌ์šฉ์ž ํ™•์ธ"
}
Loading
Loading