aboutsummaryrefslogtreecommitdiff
Commit message (Collapse)AuthorAgeFilesLines
* refactor!: collapse three time-left format defcustoms into one alistCraig Jennings2026-05-056-67/+82
| | | | | | | | | | | | | | | | | | | | | | | | I merged `chime-time-left-format-at-event', `chime-time-left-format-short', and `chime-time-left-format-long' into a single alist `chime-time-left-formats' keyed by `at-event' / `short' / `long'. Three knobs for one feature (countdown display) was unnecessary surface area; one alist is the same flexibility with a third the namespace. `chime--time-left' switched from a pcase-on-variable to a pcase-on-regime that picks an alist key, then `alist-get's the format string. Behavior is identical for default settings. Test setup in the four affected files now builds the alist with `(list (cons 'KEY VAL) ...)' instead of `'(...)'. The literal-quote form returns the SAME cons-cell structure on every evaluation, so a previous test mutating it via `setf' on `alist-get' poisoned later tests. `list' + `cons' produces fresh structure per call, which is what the tests actually need. Migration: `(setq chime-time-left-format-short "in %mm")' becomes `(setf (alist-get 'short chime-time-left-formats) "in %mm")', or a full `(setq chime-time-left-formats '((at-event . ...) (short . ...) (long . ...)))' replacement.
* refactor!: demote chime-validation-max-retries to private defvarCraig Jennings2026-05-054-52/+25
| | | | | | | | | | | | | | | | | | | | | This is an internal startup-timing parameter, not a knob real users have reason to tune through `M-x customize'. I demoted it from defcustom to defvar and renamed it to `chime--validation-max-retries' to make the private status explicit. Anyone who was overriding it can keep doing so with `setq' (the variable still exists, just under the new name). The three customize-time validation tests went away with the defcustom — nothing left to validate at customize-time once it stops being a customize-target. The setter helper still applies to the other five numeric defcustoms. Test files that referenced the variable (`test-chime-validation-retry.el', `test-integration-chime-mode.el') were renamed mechanically along with the source. Breaking change: `(setq chime-validation-max-retries N)' becomes `(setq chime--validation-max-retries N)' if you actually had it. Most users won't have touched it.
* refactor!: drop chime-play-sound, use chime-sound-file = nil to disableCraig Jennings2026-05-053-48/+17
| | | | | | | | | | | | | | | | | `chime-play-sound' was redundant with `chime-sound-file' — both had to be truthy for sound to play, and `chime-sound-file' already documented "set to nil to disable sound completely". Two knobs for one decision is a trap. I removed the defcustom and the `(when chime-play-sound ...)' guard in `chime--notify' (it now just checks `chime-sound-file'). Tests, README quick-start, and the troubleshooting checklist all reference the new single-knob form. One redundant test (sound-disabled-via-the-toggle) got dropped because it now duplicates the sound-file-nil case. Breaking change: users with `(setq chime-play-sound nil)' in their config will get a void-variable warning at customize time and lose their disable. Migration: `(setq chime-sound-file nil)'.
* fix: validate numeric defcustoms at customize-timeCraig Jennings2026-05-052-6/+228
| | | | | | | | | | | | | | | | | | | | | | | | | | Six numeric settings are declared as integers but were read straight into arithmetic and timer math. A bad value (string, negative number, nil where nil isn't supported) used to slip past the defcustom and surface as a timer error or `arith-error' deep in a callback, instead of as a configuration problem at the moment the user set it. I added `chime--validate-integer-setting' as a small shared helper and wired a `:set' on each of the affected defcustoms: - `chime-modeline-lookahead-minutes' — integer >= 0 (0 disables) - `chime-tooltip-lookahead-hours' — integer >= 1 - `chime-modeline-tooltip-max-events' — integer >= 1 or nil (show all) - `chime-day-wide-advance-notice' — integer >= 0 or nil (same-day only) - `chime-max-consecutive-failures' — integer >= 0 (0 disables warnings) - `chime-validation-max-retries' — integer >= 0 (0 = fail immediately) The constraints follow each docstring's stated intent. The helper signals `user-error', so `customize-set-variable' surfaces it as a config problem rather than a generic error trace. Tests: 22 cases in `tests/test-chime-numeric-defcustom-setters.el' — five direct on the helper plus each defcustom's accept/reject paths through `customize-set-variable'.
* fix: stop tooltip dedup from hiding distinct events sharing a titleCraig Jennings2026-05-052-14/+76
| | | | | | | | | | | | | | | | | `chime--deduplicate-events-by-title' was keying off the user-facing title alone, so two real "1:1" entries on different days collapsed to one and the second one disappeared from the tooltip. I changed the key to `(marker-file . marker-pos)' — the source heading identity — so distinct headings keep both copies and recurring expansions of one heading still fold to the soonest. When marker info is missing (synthesized test events, edge cases) the key falls back to title, which preserves the older fixtures the function was originally tested against. Three new tests cover the regression paths: two distinct headings sharing a title both survive, one heading expanded into multiple instances still collapses to the soonest, and a mix of sourced and unsourced events behaves correctly under both code paths.
* ci: flip lint job from advisory to requiredCraig Jennings2026-05-051-6/+1
| | | | | | | The lint backlog is now zero — all three checks (package-lint, checkdoc, elisp-lint) are clean. Drop `continue-on-error: true' from each step so a regression actually fails the build instead of quietly turning the job green.
* refactor: clear the rest of the lint backlog and make `make lint' actually workCraig Jennings2026-05-056-183/+61
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Took the package-lint commit's foundation and finished the job. Three groups of changes: 1. **checkdoc** is now clean across all three package files. I worked through every warning: 13 missing-double-space-after-period fixes, 4 message-capitalization fixes, 1 trailing-period-on-error fix, 6 Lisp-symbol-should-be-quoted fixes, and one rephrase from "starts" to the imperative "Log the start of an async check". One `chime-debug.el' docstring also exceeded 80 columns and got split into two lines. 2. **`make lint'** ran elisp-lint but had been silently broken. The shell glob `test-*.el' wasn't expanding (CWD ended up at project root, not tests/), and the noisy validators flagged everything. I rewrote the target to lint package files explicitly via absolute paths, preload chime.el so the byte-compiler sees cross-file symbols when checking chime-debug.el, and disable the validators that conflict with project style or duplicate other lint steps: - `--no-checkdoc' (covered by `eask lint checkdoc') - `--no-package-lint' (covered by `eask lint package'; running it on auxiliary files re-flags them as standalone packages) - `--no-indent-character' (project uses spaces per `.claude/rules/elisp.md'; the validator defaults to tabs) - `--no-fill-column' (project allows up to 80; validator defaults to 70) - `--no-indent' (false-positives on dash threading macros `->'/`->>') The validators-disabled list is documented in the recipe header. 3. **Generated autoload files** (`chime-autoloads.el', `tests/tests-autoloads.el') are now gitignored. `tests/tests-autoloads.el' was tracked from an earlier commit; I removed it from the index. Eask regenerates these on every `eask compile' / `eask install-deps' run, so they don't belong in the tree. Verified: `make compile' clean (with byte-compile-error-on-warn t), `make test-all' green at 677 tests, `eask lint package' clean, `eask lint checkdoc' clean, `make lint' clean. Full lint backlog is now zero across all three checks.
* refactor: clear package-lint warnings for MELPA prepCraig Jennings2026-05-056-59/+73
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | I worked through the package-lint backlog and got it to zero. Five changes: 1. Renamed six interactive debug commands from the private `chime--debug-*' prefix to the public `chime-debug-*' form. They were always M-x targets, so the private prefix was just wrong. The autoload cookies stay because public commands SHOULD be autoloaded. README, docstring references in chime.el, and the matching tests follow the rename. 2. Dropped `Version', `Package-Requires', and `Keywords' headers from chime-org-contacts.el. Auxiliary files in a multi-file package shouldn't carry their own metadata — package-lint flags it as an error because the headers have no effect outside the main file. The main file (chime.el) already declares the chime package's metadata. 3. Dropped `Keywords' from chime-debug.el for the same reason. 4. Dropped the auto-loader for the optional chime-org-contacts integration from chime.el. The old code used `with-eval-after-load 'org-capture' to pull the file in, which package-lint flags as a configuration pattern that doesn't belong in a package. Users who want the integration now require it themselves; the README shows both the plain `with-eval-after-load' pattern and the `use-package :after' form. chime-org-contacts.el's internal `with-eval-after-load' went away too — by the time the user has required the file, they've already gated it on org-capture being loaded, so the inner check is redundant. 5. Dropped the redundant `with-eval-after-load' from chime-org-contacts.el's activation block. The setup function still guards on `(boundp 'org-capture-templates)' so it's safe to require either order. Behavioral note: this is a small breaking change for anyone whose config relied on the auto-load. The README change spells out the migration path.
* test: replace string-search with portable form for Emacs 27.1Craig Jennings2026-05-051-11/+11
| | | | | | | | `string-search' was added in Emacs 28.1. Since chime's package floor is 27.1, the convert-org-contacts-birthdays test file failed on that version in CI. I swapped each `string-search NEEDLE HAYSTACK' for the equivalent `string-match-p (regexp-quote NEEDLE) HAYSTACK', which works on 27.1+ and returns a truthy value the same way.
* ci: add GitHub Actions workflow with test matrix, lint, and coverageCraig Jennings2026-05-053-12/+122
| | | | | | | | | | | | | | | | | | | | | | | | | I added `.github/workflows/ci.yml` with three jobs: 1. test — Emacs 27.1 / 28.2 / 29.4 / 30.1, runs `make compile` (strict warnings) and `make test-all`. fail-fast off so one version's failure doesn't hide others. 2. lint (advisory) — `eask lint package`, `eask lint checkdoc`, and `make lint` (elisp-lint). All three are `continue-on-error: true` because there's an existing MELPA-prep backlog (1 package-lint error in chime-org-contacts.el, ~17 cosmetic checkdoc/package-lint warnings) that's worth surfacing without blocking CI. Tighten to required once the backlog is cleared. 3. coverage — runs the full suite with undercover and uploads to Coveralls via the official action. No secret needed because the repo is public — GITHUB_TOKEN is enough. Two supporting changes: - `tests/run-coverage-file.el` now switches between simplecov (local) and coveralls (CI, detected via the `CI` env var GitHub Actions sets automatically) report formats. The Coveralls action expects coveralls JSON. - `Makefile`'s `coverage' target now runs ALL_TESTS with selector `t', not UNIT_TESTS with `(not (tag :slow))'. Without this the integration tests contributed nothing to the reported coverage number.
* chore: bump version to 0.7.0v0.7.0Craig Jennings2026-05-052-2/+2
| | | | | Header version in chime.el and the Eask manifest both move from 0.6.0 to 0.7.0 for the v0.7.0 release.
* fix: skip declined events in tooltip, modeline, and notificationsCraig Jennings2026-05-052-1/+166
| | | | | | | | | | | | | | | | | | org-gcal writes `:STATUS: declined' on calendar entries the user has declined, and chime was happily showing them in the tooltip, modeline, and notification stream — which defeats the whole point of declining a meeting. I added `chime-declined-events-predicate', mirroring the shape of `chime-done-keywords-predicate', and put it on the default `chime-predicate-blacklist'. The match is on the literal lowercase value because that's what real org-gcal exports use; uppercase or other values pass through. Users who want declined events back can pop the predicate off the blacklist. Tests cover all four STATUS values seen in real org-gcal data (accepted, declined, needs-action, tentative), plus the no-property, empty-property, todo-keyword-still-attached, gibberish-value, case-sensitivity, and default-blacklist-membership cases.
* test: tag integration suite :slow and unstick test-allCraig Jennings2026-05-054-1/+16
| | | | | | | | | | | | | | | I tagged the 15 end-to-end tests across `test-integration-chime-mode.el`, `test-integration-recurring-events-tooltip.el`, and `test-integration-startup.el` with `:tags '(:slow)`. The default `make test` now runs only the 652 fast unit tests; `make test-all` runs the full 667. While verifying, I hit a pre-existing bug in `tests/Makefile` where `test-all`'s `--eval '(ert-run-tests-batch-and-exit)'` came back from eask's argv passthrough with its quotes stripped, which broke shell parsing. Passing the explicit `t` selector dodges whatever eask does to no-arg single-quoted forms. The bug only mattered once integration tests were `:slow` — before that, `test-all` overlapped fully with `test-unit` plus `test-integration`, so nothing actually depended on it working.
* build: fail compile on byte-compile warningsCraig Jennings2026-05-051-3/+3
| | | | | | I set `byte-compile-error-on-warn` to t in the root `compile' target. The warning backlog is clear, so any new warning should break the build instead of slipping by silently.
* chore: drop non-standard keywords from chime.el headerCraig Jennings2026-05-051-1/+1
| | | | | | Eask flagged `agenda`, `chime`, and `sound` as unknown finder keywords. The Eask manifest already lists the canonical set (notification, alert, org, org-agenda, calendar), so I trimmed the in-file header to match.
* fix: remove unused `title` lexical in chime--process-notificationsCraig Jennings2026-05-051-2/+1
| | | | | | | `make compile' flagged it. The variable was bound but never referenced in the bundled-notification branch, so I dropped the `let' binding. Whether the bundled notification should actually carry that title is a separate concern, not this fix.
* fix: trim chime--find-soonest-modeline-event docstring to <=80 colsCraig Jennings2026-05-051-2/+3
| | | | | | `make compile' flagged the summary line at 86 chars. I split it across two lines, with the lookahead clause and the return-value sentence on the lines after.
* build: add eask manifest and setup/compile/coverage targetsCraig Jennings2026-05-055-91/+278
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | I switched the test runner from `~/.emacs.d/elpa`-grep to eask. With this, `make setup` installs every dep into a project-local `.eask/`, so test runs don't depend on whatever's in my global elpa. It also lets us catch missing Package-Requires entries before MELPA submission. New targets: - `make setup` — runs `eask install-deps --dev` - `make compile` — byte-compiles chime.el and surfaces warnings that checkdoc and elisp-lint don't catch - `make coverage` — runs the unit suite under undercover and writes a simplecov JSON to `.coverage/simplecov.json` - `make test-all` — runs every test, including `:slow` tagged - `-include makefile-local` in both Makefiles, for per-machine knobs I added `ERT_FAST_SELECTOR` so `make test`, `test-unit`, `test-integration`, and `test-file` exclude tests tagged `:slow`. When we tag end-to-end integration tests as `:slow`, they'll stay out of the fast feedback loop until someone explicitly asks for them via `make test-all`. Eask treats CWD as its workspace. So all eask invocations now run from project root, with `(cd "tests/")' as the first `--eval' to restore Emacs's default-directory. That preserves the relative loads the existing test files and test-bootstrap.el rely on, without touching either. I updated `.gitignore` for `.eask/`, `.coverage/`, and the optional `makefile-local` files.
* refactor: rewrite chime--time-left without threading-pcaseCraig Jennings2026-05-051-7/+9
| | | | | | | | Edebug's defun parser rejects the `(-> seconds (pcase ...) ...)' form, so undercover can't instrument chime.el and `make coverage' produces nothing. The let-bound rewrite is equivalent and parses cleanly. I left an inline note so the form doesn't get folded back later.
* adding to gitignoreCraig Jennings2026-04-241-0/+1
|
* refactor: move 12 internal helpers from chime- to chime-- prefixCraig Jennings2026-04-228-157/+157
| | | | | | | | | | Before MELPA submission, tighten the public API surface. Single-dash chime-foo is the convention for user-facing commands and predicates that external code can bind. Anything that is not meant to be bound externally should use the double-dash chime--foo prefix so byte-compile warnings, docstrings, and MELPA package inspection all point in the same direction. Twelve helpers in chime.el had single-dash names but no user-facing role. They are not mentioned in README, they carry no interactive declaration, and their docstrings do not promise a behavior contract. Rename them: chime-get-minutes-into-day, chime-get-hours-minutes-from-time, chime-set-hours-minutes-for-time, chime-current-time-matches-time-of-day-string, chime-current-time-is-day-wide-time, chime-day-wide-notifications, chime-display-as-day-wide-event, chime-event-has-any-day-wide-timestamp, chime-event-within-advance-notice-window, chime-event-has-any-passed-time, chime-event-is-today, chime-environment-regex. The public API surface is now intentional. It covers chime-mode, chime-validate-configuration, chime-refresh-modeline, chime-done-keywords-predicate, and the chime-debug-* interactive commands in chime-debug.el. Breaking change. No alias shims because there are no downstream users yet.
* test: add unit tests for chime--day-label-for-event-timeCraig Jennings2026-04-221-0/+71
| | | | | | | | | | Seven pure-function tests appended to the group-events-by-day file, covering Normal and Boundary cases. Normal: event on the same calendar day as NOW returns "Today, ...". Event on the same calendar day as TOMORROW returns "Tomorrow, ...". Event three days out returns a weekday label and is neither Today nor Tomorrow. Boundary: event at 00:00 on the NOW calendar day is Today. Event at 00:00 on the TOMORROW calendar day is Tomorrow. Event two calendar days out is not Tomorrow, gets a weekday label. Event on the previous calendar day is neither Today nor Tomorrow. Since NOW and TOMORROW are function arguments, the tests use encode-time to build stable calendar values and skip the clock-mocking dance.
* refactor: extract chime--day-label-for-event-time from ↵Craig Jennings2026-04-221-29/+30
| | | | | | | | chime--group-events-by-day The date-string computation mixed the today/tomorrow/weekday label selection in with the grouping loop and carried its own pre-decoded copies of NOW and TOMORROW through five let-bindings before it could decide which branch to take. Lift the selection into chime--day-label-for-event-time (event-time now tomorrow). The outer function becomes pure grouping, the label logic gets its own test target, and future label tweaks (localized strings, a "Yesterday" branch for overdue items) edit one helper. The outer function drops from 36 to 15 lines. The redundant (when event-decoded) guard is replaced by (when event-time) because decode-time always returns a struct for valid time values.
* test: pin group-events-by-day clock and add midnight edge casesCraig Jennings2026-04-221-94/+123
| | | | | | | | | | The Normal and Boundary tests built events as fixed-minute offsets from real current-time. On late-night runs the +60 minute event in single-day crossed midnight and the test failed because events 1-2 landed "Today" while event 3 landed "Tomorrow". The intent of these Normal tests is routine grouping, not midnight behavior, so they should be deterministic. Pin the clock with with-test-time using the established let-bind pattern. with-test-time re-evaluates BASE-TIME inside the mocked current-time lambda, so passing test-time-today-at directly would recurse, because the helper itself calls current-time. Add two new Boundary tests that explicitly exercise the day-crossing logic at 23:50. One event at +5 minutes stays in Today and one at +20 minutes crosses into Tomorrow. These are the first tests in the file that actually target midnight behavior. Drop stale "REFACTORED: Uses dynamic timestamps" annotations from docstrings since the behavior is documented at the file level.
* test: add unit tests for async result helpersCraig Jennings2026-04-221-0/+147
| | | | | | | | Eight tests in a new file covering Normal and Boundary cases for both new helpers. chime--record-async-failure increments the consecutive-failure counter, sets chime-modeline-string to the standard error tooltip, triggers the threshold warning when the counter hits chime-max-consecutive-failures, and leaves chime-modeline-string alone when chime-modeline-no-events-text is nil. chime--handle-async-success resets the counter from non-zero to zero, invokes the callback with the events list, works with an empty events list, and is a no-op on the counter when it already starts at zero.
* refactor: extract async result helpers from chime--fetch-and-processCraig Jennings2026-04-221-27/+26
| | | | | | chime--fetch-and-process inlined two near-identical 7-line failure-handling blocks inside the async callback. They differed only in the log prefix ("Async error" for errors surfaced by the async process, "Error processing events" for errors thrown by the callback). Lift the shared body into chime--record-async-failure (err prefix) so the sequence lives in one place, and lift the success path into chime--handle-async-success (callback events) so the callback lambda becomes pure dispatch. The outer function drops from 44 lines to 22.
* fix: load convert-org-contacts-birthdays from load-pathCraig Jennings2026-04-211-3/+1
| | | | | | The previous form computed the file path at compile time via (file-name-directory (or load-file-name buffer-file-name)). Under emacs --batch byte-compile, both load-file-name and buffer-file-name are nil, so the inner expand-file-name call signaled "Wrong type argument: stringp, nil" and blocked validate-el.sh from accepting any edit to chime-org-contacts.el. convert-org-contacts-birthdays.el lives next to chime-org-contacts.el, so it is already on the load-path whenever chime-org-contacts is loadable. Drop the explicit path argument and let require resolve via load-path.
* test: add unit tests for chime--render-modeline-stringCraig Jennings2026-04-211-0/+52
| | | | | | | | | | Five tests covering Normal and Boundary cases. Normal: SOONEST branch applies chime-modeline-format to the event-text. Normal: no SOONEST plus UPCOMING binds mouse-1 (open calendar) and mouse-3 (jump to event). Normal: no SOONEST and no UPCOMING binds only mouse-1, and the tooltip is the no-events message. Boundary: returns nil when no SOONEST and chime-modeline-no-events-text is nil. Boundary: SOONEST branch renders regardless of whether chime-modeline-no-events-text is set. The orchestrator chime--update-modeline already exercises these paths via test-chime-update-modeline.el. These direct unit tests give the helper its own coverage.
* refactor: extract chime--render-modeline-string from chime--update-modelineCraig Jennings2026-04-211-25/+30
| | | | | | | | chime--update-modeline grew to mix orchestration with the modeline-string formation logic. Extract the formation block into its own helper so the orchestrator reads as pure orchestration: build upcoming, find soonest, render, force update. The helper handles both branches. When a soonest event is in the modeline window, format and propertize via chime--propertize-modeline-string. Otherwise, when chime-modeline-no-events-text is set, propertize that with the appropriate tooltip and click handlers (mouse-1 always, mouse-3 only when there are upcoming events to jump to). The orchestrator drops from 45 to 25 lines.
* fix(hooks): run validate-el test phase from tests/ directoryCraig Jennings2026-04-211-1/+4
| | | | | | Test files start with (require 'test-bootstrap (expand-file-name "test-bootstrap.el")). The expand-file-name call resolves against default-directory, which in batch mode is the directory the shell was in when emacs started. The hook ran emacs from the project root, so the require looked for the bootstrap at the project root and could not find it. Every Edit or Write to a test file failed the hook. The fix is to cd into PROJECT_ROOT/tests inside the subshell before launching emacs, so the bootstrap require resolves to tests/test-bootstrap.el where the file actually lives.
* docs: expand custom predicate examples in READMECraig Jennings2026-04-201-7/+22
| | | | | | | Fill out the custom-predicate-filtering section with the two motivating examples from the surrounding prose (specific-file whitelist, weekend work silencer) plus a priority-A whitelist, and tighten the defensive handling of buffer-file-name for indirect buffers.
* chore: ignore .stignore (syncthing)Craig Jennings2026-04-201-0/+1
|
* restructure: move docs/ to .ai/ + sync latest templateCraig Jennings2026-04-201-1/+1
| | | | | Per claude-templates c36fd14. Claude tooling moves to hidden .ai/; project-level docs/ reserved for real documentation.
* chore(claude): sync validate-el.sh JSON channel + pairwise rule from rulesetsCraig Jennings2026-04-192-9/+44
|
* chore: sync testing rules — pyramid, overmocking, ↵Craig Jennings2026-04-192-0/+130
| | | | refactor-for-testability, interactive/internal split
* chore: sync elisp-testing.md (testutil pattern generalized)Craig Jennings2026-04-191-3/+3
|
* chore: sync bundle — add commits.md rule, attribution suppressionCraig Jennings2026-04-192-0/+70
| | | | | | - New .claude/rules/commits.md: no AI attribution, conventional prefixes. - settings.json: attribution.commit and attribution.pr empty strings. - CLAUDE.md template refreshed to reference commits.md.
* chore: add Claude Code ruleset via ~/code/rulesets install-elispCraig Jennings2026-04-198-0/+564
| | | | | | | | | | | | | | | | | | Installs the Elisp ruleset from the rulesets repo: - CLAUDE.md (project instructions template) - .claude/rules/ (testing, verification, elisp, elisp-testing) - .claude/hooks/validate-el.sh (check-parens + byte-compile + run matching tests on every .el edit via PostToolUse) - .claude/settings.json (permission allowlist + hook wiring) - githooks/pre-commit (secret scan + staged-file paren check) core.hooksPath set to githooks/ so the pre-commit activates automatically. Hooks use \$CLAUDE_PROJECT_DIR with a script-relative fallback, so a fresh clone works without path edits. .gitignore extended with personal-override entries (settings.local.json, .cache/) and byte-compile artifacts (*.elc, *.eln).
* Improve README quick start, manual install, and filtering docsCraig Jennings2026-04-041-59/+60
| | | | | | | | Rewrote Quick Start to show minimal config (just chime-mode 1) with defaults overview and modeline interaction guide. Expanded manual install with git clone steps. Fixed TOC nav links, made tag filter examples consistent, added custom predicate motivation, removed redundant Basic Event subsection.
* Add personality and reorganize READMECraig Jennings2026-04-041-264/+135
| | | | | | | Add Douglas Adams epigraph, funny event names throughout, voice in installation and history sections. Consolidate org-contacts into new Integrations section with org-gcal guide. Trim verbose all-day events interaction examples. Add severity, sound format, and icon docs.
* Fix TOC formatting in TESTING.orgCraig Jennings2026-04-041-3/+1
|
* Add table of contents to TESTING.orgCraig Jennings2026-04-041-0/+4
|
* Rewrite TESTING.org with current test infrastructureCraig Jennings2026-04-041-176/+275
| | | | | | Replaced stale 339-test/23-file doc with current state (645 tests, 53 files). Documents test-bootstrap.el, testutil libraries, Makefile consolidation, and all convenience macros.
* Remove duplicate COPYING fileCraig Jennings2026-04-041-674/+0
| | | | | LICENSE and COPYING were identical. Keep LICENSE since README links to it and GitHub recognizes it automatically.
* Consolidate Makefiles and update TESTING.orgCraig Jennings2026-04-042-129/+73
| | | | | | Root Makefile now delegates to tests/Makefile. Fixed stale UNIT_TESTS/INTEGRATION_TESTS definitions, added test-name target, switched to per-file test execution for better isolation.
* Add tests for chime-environment-regexCraig Jennings2026-04-041-0/+62
| | | | | Verify the regex matches all default variable names, picks up additional user-configured regexes, and handles empty additional list.
* Decompose chime--debug-notification-filtering into step functionsCraig Jennings2026-04-041-71/+71
| | | | | | | | | The 120-line diagnostic function is now a 30-line coordinator calling four focused helpers: - chime--debug-filter-check-timestamp - chime--debug-filter-check-time-match - chime--debug-filter-check-interval - chime--debug-filter-check-pipeline
* Remove unused chime--today functionCraig Jennings2026-04-042-88/+0
| | | | Defined and tested but never called from any production code.
* Bundle multiple day-wide events into a single notificationCraig Jennings2026-04-042-2/+67
| | | | | | | | | | When all-day event alert times trigger, multiple events (overdue tasks, birthdays, holidays) previously fired individual notifications — one sound and one popup each. With 8-10 events this was overwhelming. Now multiple day-wide events are bundled into a single notification with all messages joined by newlines. Single events still notify normally without bundling.
* Restructure README and address review commentsCraig Jennings2026-04-043-151/+828
| | | | | | | | | | | | | | - Remove About section (merged into intro) - Rename Credits to History, fold Migration under it - Fold Manual Check and Known Limitations under Usage - Fold Full Example Configuration under Configuration - Add straight.el and quelpa install methods - Move requirements into Installation with auto-deps note - Add notification daemon check to troubleshooting - Add Development subsection with clone/lint/issues info - Add LICENSE file (GPL-3.0) - Update nav bar to match new structure - Fix startup integration test for new modeline error state