Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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
3 changes: 2 additions & 1 deletion ARCHITECTURE.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# ARCHITECTURE.md

Last updated: 2026-03-10
Last updated: 2026-03-11

## Brand source

Expand Down Expand Up @@ -89,6 +89,7 @@ Last updated: 2026-03-10
- 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