diff --git a/CHANGELOG.md b/CHANGELOG.md index 091b566a..4639c0a3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,15 +18,37 @@ heading, and (b) bumping `project.yaml` `version:` in the same commit. ### Added +- Josefin Sans bundled as `app/assets/fonts/josefin_sans/` as the + application UI face — variable-font pair (upright + italic, weight + range 100-700), OFL-licensed. Declared as the `JosefinSans` family + in `app/pubspec.yaml`. `_AppRoot` installs it as the ambient + `DefaultTextStyle` at weight `w300` (Light) per the project's + aesthetic direction; callers can still pass an explicit + `fontWeight` on `ClideText` to get bolder emphasis. + - JetBrains Mono bundled as `app/assets/fonts/jetbrains_mono/` — Regular / Italic / Bold / BoldItalic weights (OFL-licensed, license file checked in alongside). Declared as the `JetBrainsMono` family in `app/pubspec.yaml`. `app/lib/widgets/src/typography.dart` - exposes `clideMonoFamily` + `clideMonoFamilyFallback` for terminal - panes and any other monospace surface; fallback chain covers - macOS / Linux / Windows for the web build path and for harnesses - that don't load asset fonts. Additional weights - (Thin/Light/Medium/ExtraBold) can be added on demand. + exposes `clideUiFamily` + `clideMonoFamily` plus platform-ordered + fallback chains for both faces, for web builds and harnesses that + don't load asset fonts. + +- `app/assets/licenses.yaml` — canonical manifest of every bundled + third-party artefact (fonts today; Dart packages + native tools as + they land). Schema has name, kind, version, homepage, license, + `license_file` pointer, and a one-line purpose. Bundled alongside + the per-dep license texts. The About screen (Tier 6) will render + this file verbatim. Accompanied by + [`D-042`](decisions/tooling.md#d-042-bundled-dependencies-documented-in-licensesyaml): + adding a dep is a two-step commit (artefact + `licenses.yaml` + entry in the same changeset). + +### Changed + +- CLAUDE.md "Dependencies & supply chain" section gains the + "document every bundled dependency" rule, pointing at + `app/assets/licenses.yaml` and `D-042`. - `ptyc/` — the C PTY-spawn helper, peer of `pql` per [`D-005`](decisions/architecture.md#d-005-dart-core-sidecar-dissolved-ptyc-as-pql-peer). diff --git a/CLAUDE.md b/CLAUDE.md index e8956a9a..3b054bee 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -51,6 +51,7 @@ See `docs/initial-plan.md` for the full tier definitions and acceptance criteria ## Dependencies & supply chain - **Dart (core + app):** prefer-zero-deps. Flutter-SDK widgets first; third-party packages need justification. What stays is exact-pinned in `pubspec.yaml` (no caret ranges). Advisories reviewed before every bump; `pubspec.lock` committed. +- **Document every bundled dependency.** Every third-party artefact that ships in the clide binary — Dart packages, fonts, bundled assets, native supporter tools — is listed in [`app/assets/licenses.yaml`](app/assets/licenses.yaml) with name, kind, version, homepage, license, relative path to the bundled license text, and a one-line purpose. Adding a dep is a two-step commit: add the artefact **and** the `licenses.yaml` entry in the same changeset. The About screen (Tier 6) renders the file verbatim; until then, the list being accurate is the contract. See [`D-042`](decisions/tooling.md#d-042-bundled-dependencies-documented-in-licensesyaml). - **`ptyc` and any future native supporter tool:** no dep graph by design (libc-only for `ptyc`). "Audit" is reading the source before each bump. - `pubspec.lock` is always committed. - `make security` runs the Dart advisory review; `ci/security.sh` is the CI entry. diff --git a/app/assets/licenses.yaml b/app/assets/licenses.yaml new file mode 100644 index 00000000..49cbbc70 --- /dev/null +++ b/app/assets/licenses.yaml @@ -0,0 +1,76 @@ +# clide — bundled-dependency manifest. +# +# Every third-party artefact that ships in the clide binary is listed +# here: fonts, Dart packages, native supporter tools, bundled data. +# The About screen reads this file and renders the entries verbatim. +# +# Adding a new bundled dependency is a two-step commit: +# 1. Add the dependency itself (font file, `pubspec.yaml` entry, etc.) +# 2. Add the entry below in the same commit, so the About screen stays +# accurate and the prefer-zero-deps guardrail is enforced by the +# obvious visible consequence: an extra row in the list. +# +# See CLAUDE.md "Dependencies & supply chain" for the full rule, and +# `decisions/tooling.md` for the D-record that pins it. + +schema_version: 1 + +dependencies: + - name: JetBrains Mono + kind: font + version: "2.304" + homepage: https://github.com/JetBrains/JetBrainsMono + license: OFL-1.1 + license_file: assets/fonts/jetbrains_mono/OFL.txt + purpose: >- + Monospace face for terminal panes, diff views, code editors, and + any other monospace surface. + weights_bundled: [Regular, Italic, Bold, BoldItalic] + + - name: Josefin Sans + kind: font + version: "variable" + homepage: https://fonts.google.com/specimen/Josefin+Sans + license: OFL-1.1 + license_file: assets/fonts/josefin_sans/OFL.txt + purpose: >- + Application UI face. Default weight Light (300); full 100-700 + range available via the variable-font weight axis. + weights_bundled: [VariableFont, Italic-VariableFont] + + - name: yaml + kind: dart-package + version: "3.1.3" + homepage: https://pub.dev/packages/yaml + license: MIT + purpose: >- + YAML parser for theme files and extension manifests. The one + justified exception to prefer-zero-deps; Dart-team maintained. + + - name: mocktail + kind: dart-package + version: "1.0.4" + homepage: https://pub.dev/packages/mocktail + license: MIT + purpose: >- + Test-only. Mocks at IO / IPC boundaries. ChangeNotifier facades + use hand-rolled fakes instead of mocks (D-025). + scope: dev + + - name: alchemist + kind: dart-package + version: "0.12.1" + homepage: https://pub.dev/packages/alchemist + license: MIT + purpose: >- + Test-only. Golden-test framework; Ahem-font rendering for + cross-platform pixel stability on widget primitives (D-024). + scope: dev + + - name: flutter_lints + kind: dart-package + version: "6.0.0" + homepage: https://pub.dev/packages/flutter_lints + license: BSD-3-Clause + purpose: Test-only. Flutter-team-recommended analyzer lint set. + scope: dev diff --git a/app/pubspec.yaml b/app/pubspec.yaml index a4374f35..37b58133 100644 --- a/app/pubspec.yaml +++ b/app/pubspec.yaml @@ -53,6 +53,13 @@ flutter: assets: - lib/kernel/src/theme/themes/ - lib/kernel/src/i18n/catalog/ + # Bundled-dependency manifest — read by the About screen. + # See CLAUDE.md "Dependencies & supply chain" and D-042. + - assets/licenses.yaml + # License files referenced by licenses.yaml must be bundled too so + # the About screen can display each dependency's full license text. + - assets/fonts/jetbrains_mono/OFL.txt + - assets/fonts/josefin_sans/OFL.txt # Bundled fonts. OFL-licensed; license files live alongside each. # diff --git a/decisions/tooling.md b/decisions/tooling.md index 52ca3f01..c11d353a 100644 --- a/decisions/tooling.md +++ b/decisions/tooling.md @@ -18,6 +18,13 @@ Toolchain, supply chain, CI, ignore strategy. - **Cost:** PRs don't run CI yet; `make push-check` is the gate until activation. - **Raised by:** 2026-04-21 planning. +### D-042: Bundled dependencies documented in `licenses.yaml` +- **Date:** 2026-04-22 +- **Decision:** Every third-party artefact bundled into the clide binary — Dart packages, fonts, native supporter tools, bundled data — has an entry in `app/assets/licenses.yaml` with name, kind, version, homepage, license identifier, relative path to the bundled license text, and a one-line purpose. The file is shipped as a Flutter asset and rendered by the About screen (Tier 6). Adding a bundled dependency is a two-step commit: add the artefact **and** the corresponding `licenses.yaml` entry in the same changeset. +- **Rationale:** Complements [D-031](#d-031-prefer-zero-deps-exact-pin). Prefer-zero-deps is a *budget*; `licenses.yaml` is the *visible consequence*. An extra row in the About screen is a review-time signal that the budget just grew. It also discharges the redistribution obligations bundled licenses impose (OFL, MIT, BSD all require preserving the license text alongside the binary) without ad-hoc NOTICE files. +- **Cost:** One extra edit per dep. Zero tolerance for drift — an un-listed dep is a contributor-visible bug. Until the About screen lands at Tier 6, `licenses.yaml` is accurate but not rendered; the discipline applies from now regardless so Tier 6 inherits a clean list. +- **Raised by:** 2026-04-22 planning (user-directed best practice). + ### D-033: Golden-output ignore pattern — `coverage.*` excludes output, not scripts - **Date:** 2026-04-21 - **Decision:** `.gitignore` excludes `coverage.*` (the lcov output files from `flutter test --coverage`). Coverage-related scripts are named `ci/test_coverage.sh` (not `ci/coverage.sh`) to stay outside the pattern.