Commit graph

484 commits

Author SHA1 Message Date
formax68
5f3cfa9979 chore(release): cut 1.15.0 — Directory Compliance milestone 2026-05-17 18:31:45 +03:00
formax68
d3a461b17d docs(phase-08): evolve PROJECT.md after phase completion 2026-05-17 16:41:38 +03:00
formax68
1236c789da docs(phase-08): complete phase execution 2026-05-17 16:40:36 +03:00
formax68
5e98d96a0a test(08): resolve scorecard UAT via lint-as-proxy override 2026-05-17 16:38:41 +03:00
formax68
0df4753f43 test(08): persist human verification items as UAT 2026-05-17 16:35:18 +03:00
formax68
e2ea050e7e docs(08): add code review report 2026-05-17 16:30:36 +03:00
formax68
4bd1cb93ff docs(phase-08): update tracking after wave 5 2026-05-17 16:23:11 +03:00
formax68
28c3f00cd3 docs(08): add Directory Compliance conventions (DOC-02)
Closes v1.15 Directory Compliance milestone.

Adds `## Directory Compliance` section to
.planning/codebase/CONVENTIONS.md with 4 clusters (DOM API,
Lifecycle & Compatibility, Type Hygiene, Release & Docs) — one
4-line Don't/Do/Why/Docs block per rule, links to canonical
Obsidian / ESLint / typescript-eslint docs.

Replaces stale `## TODO: Code Quality Issues to Address` block in
CLAUDE.md (lines 182-236) with a `## Directory Compliance` pointer
section that links to the canonical doc. `### Memory Reminders`
and `### Beta Release Strategy` (BRAT workflow) both preserved
verbatim — bounded replacement only touches lines 182-236. CLAUDE.md
is gitignored project-wide so the edit lives in the working tree;
08-05-CLAUDE-md-change.md records the change for planning history.

Lint sites resolved across Phase 8:
- 18 no-unused-vars (Plan 01)
- 16 no-explicit-any + 1 no-case-declarations + 1 no-useless-escape (Plan 02)
- 39 no-console (33 deleted, 6 gated behind \`const DEBUG = false\`) (Plan 03)
- 0 ??-with-constant-LHS in executable code (audit clean)
- Phase-8 eslint.config.mjs override block deleted + D-08-extension
  narrow override added for src/**/*.ts no-unsafe-* (Plan 04)
- CalendarService.ts:303 console.log -> console.debug; 6 Plan-03
  unused eslint-disable-next-line no-console directives removed (Plan 04)

Verification:
- npm run lint: clean
- npm run build: clean
- Obsidian smoke test (8 steps): all green
2026-05-17 16:22:48 +03:00
formax68
0880d4a93b chore: merge executor worktree (worktree-agent-a9f8e53d9151b63c3) 2026-05-17 16:21:00 +03:00
formax68
dc290392e7 docs(08-05): replace stale TODO block in CLAUDE.md with Directory Compliance pointer (DOC-02 part B)
Replaces ## TODO: Code Quality Issues to Address (lines 182-236) with
## Directory Compliance pointer section linking to the canonical rule
list in .planning/codebase/CONVENTIONS.md#directory-compliance.

Preserved verbatim:
- ### Beta Release Strategy (BRAT workflow, line 66)
- ### Memory Reminders (no Claude/AI references in commits)

CLAUDE.md is gitignored (line 28 of .gitignore) — the file was updated
in-place in the working directory. This commit records the change via
.planning/phases/08-type-hygiene-conventions/08-05-CLAUDE-md-change.md.
2026-05-17 10:45:17 +03:00
formax68
d32998fc6a docs(08-05): append Directory Compliance section to CONVENTIONS.md
Appends ## Directory Compliance to .planning/codebase/CONVENTIONS.md
with 4 rule clusters (DOM API, Lifecycle & Compatibility, Type Hygiene,
Release & Docs) — 16 rule blocks total in the 4-line Don't/Do/Why/Docs
format per D-03. Includes Verifying compliance bash snippet.

Closes DOC-02 part A (single source of truth for directory-compliance
rules; ESLint enforces each rule via eslint.config.mjs).
2026-05-17 10:18:14 +03:00
formax68
7543082ee9 docs(phase-08): update tracking after wave 4 2026-05-17 10:14:10 +03:00
formax68
f109a23694 chore: merge executor worktree (worktree-agent-af9f52ce569d1c7f0) 2026-05-17 10:13:28 +03:00
formax68
e09155f744 docs(08-04): complete Plan 04 — Phase-8 override block deleted, lint passes clean 2026-05-17 10:13:10 +03:00
formax68
9d042ebe89 chore(lint): remove Phase 8 ESLint overrides + add D-08-extension (DIR-01/09/10 acceptance)
Deletes the contiguous Phase-8 override block from eslint.config.mjs
(lines 73-113 — the `// Phase 8 — DIR-01 / DIR-09 / DIR-10` headers
and both sub-blocks).

Adds the D-08-extension override (a `src/**/*.ts no-unsafe-*: off`
block) that mirrors the existing `**/*.d.ts no-explicit-any: off`
exclusion's strategy: silence the typed-linting cascade from
ical.js's untyped APIs at the consumption sites, since the root-
cause fix (hand-typing ical.js) is deferred to FRAG-02. The new
override is NOT tied to a scorecard finding — `no-unsafe-*` is
not a DIR-NN rule.

Closes scorecard findings DIR-01, DIR-09, DIR-10 at the acceptance
level: `npm run lint` now passes clean. Remaining narrow overrides:
- Phase-5 tightening (no-unused-vars: error, no-restricted-syntax
  for document.createElement)
- `**/*.d.ts` no-explicit-any: off (Plan 02 — ical.d.ts shim)
- `src/**/*.ts` no-unsafe-*: off (this commit — ical.js cascade)
- globalIgnores (node_modules, main.js, build scripts)

See 08-04-CHECKPOINT.md for the Rule-4 architectural escalation
that surfaced this design (Option B was chosen).
2026-05-17 10:12:27 +03:00
formax68
c9b7dbef4f fix(08-04): clean up Plan 03 disable directives and console.log site
Plan 03 added 6 `// eslint-disable-next-line no-console -- DEBUG
flag (Phase 8 D-07)` comments expecting Plan 04 to activate
`no-console` globally. The `no-console` rule is OFF in obsidianmd's
recommended config (not just in the Phase-8 override), so the
disables never had effect — they become "unused eslint-disable
directive" warnings once the Phase-8 override is removed.

Also changes CalendarService.ts:303 from `console.log` to
`console.debug` so it complies with `obsidianmd/rule-custom-message`
(which disallows console.log but allows console.debug). The
MemoChron: prefix convention is preserved.

Removed disables: CalendarService.ts:302,388,407,458 and
timezoneUtils.ts:211,221.

Prepares the tree for the Phase-8 override-block deletion in the
next commit.
2026-05-17 10:11:36 +03:00
formax68
42380f7900 docs(08-04): amend plan with Option B + Class 2/3 housekeeping
Plan 04 paused at a Rule-4 architectural checkpoint when removing the
Phase-8 ESLint override block exposed 33 errors not anticipated by the
original plan (32 typed-linting cascade from ical.js + 1 obsidianmd/
rule-custom-message error on console.log + 6 unused eslint-disable
directives from Plan 03).

User chose Option B from 08-04-CHECKPOINT.md (narrow no-unsafe-* override
mirroring D-08's documented strategy). Amendment:

- files_modified now lists eslint.config.mjs + CalendarService.ts +
  timezoneUtils.ts (was eslint.config.mjs only).
- must_haves.truths adds D-08-extension allowance (the new src/**/*.ts
  no-unsafe-*: off block) and Class 2/3 housekeeping requirements.
- Single task split into two: Task 1 cleans up Plan 03's wrong-rule
  disables and the console.log site; Task 2 deletes the Phase-8
  override block and adds the D-08-extension.

See 08-04-CHECKPOINT.md for the full Rule-4 analysis.
2026-05-17 10:09:26 +03:00
formax68
f9b84c192e docs(state): pause phase 08 at plan 04 checkpoint 2026-05-17 10:03:18 +03:00
formax68
74562f858e docs(08-04): preserve checkpoint analysis (architectural blocker)
Plan 08-04 reached an architectural checkpoint during execution:
deleting the phase-8 ESLint override surfaced 33 errors + 6 warnings
from a typed-linting cascade rooted in ical.d.ts (any returns).
The cascade was not inventoried in 08-RESEARCH.md because the override
block silenced it at inventory time.

CHECKPOINT.md (renamed from SUMMARY.md to keep the plan open) documents
three resolution options. Plan stays incomplete in ROADMAP until the
phase is resumed with a decision on the cascade.
2026-05-17 10:03:13 +03:00
formax68
ad33d3ea80 docs(phase-08): update tracking after wave 3 2026-05-17 09:53:05 +03:00
formax68
099c52b290 chore: merge executor worktree (worktree-agent-a3d0d33ce60cf7c6c) 2026-05-17 09:53:02 +03:00
formax68
4350e2d9a1 docs(08-03): summarize DIR-01 console cleanup wave
Wave 3 closes DIR-01 at the source level. 33 sites deleted, 6 gated
behind per-file const DEBUG = false in CalendarService.ts and
timezoneUtils.ts. Aggregate: 0 bare console.* in src/; rule-explicit
no-console lint pass clean; npm run lint and npm run build clean.

Plan 04 will remove the global no-console override at eslint.config.mjs;
the per-line eslint-disable directives on the 6 gated sites are in place
so that removal lands clean.
2026-05-17 09:52:34 +03:00
formax68
6018b6a2b3 refactor(08-03): delete console.* in remaining files per DIR-01
DIR-01 progress (Task 3 of 4). 20 console.* sites deleted across 7 files:
- main.ts (2): invalid-color load-time validation warnings
- services/NoteService.ts (6): all silent-recovery or caller-handles paths
- services/IcsImportService.ts (2): timezone-registration noise (debug/warn)
- settings/SettingsTab.ts (2): missing-custom-settings + lifecycle log
- views/CalendarView.ts (6): all paired with Notice or silent fallback
- views/EmbeddedCalendarView.ts (1): daily-note open failure (Notice paired)
- views/EmbeddedAgendaView.ts (1): daily-note open failure (Notice paired)

Aggregate so far: 30 deleted across these 7 files + Task 1's 10 + Task 2's 3
= 33 deleted; 6 gated (Tasks 1 and 2). Total 39 sites closed (matches the
phase frontmatter must_haves declaration; the plan task header that said
'19 sites total' was off-by-one, the underlying per-file breakdown is 20).

Adjacent cleanup (caused by deletions):
- CalendarView: empty try/catch wrappers collapsed to `catch {}` where the
  error binding was solely the deleted console.error argument
- CalendarView event-click .catch: replaced 'Check the console for details'
  Notice text with errorMessage(error) inline (the console it referenced
  no longer exists — Rule 1 user-visible-signal preservation)
- NoteService.createEventNote: removed useless try/catch wrapper that only
  re-threw (no-useless-catch lint error after console.error deletion)
- IcsImportService timezone-registration catch: collapsed if/else branches
  whose only difference was console.debug vs console.warn into a single
  silent catch {}
2026-05-17 09:50:13 +03:00
formax68
d959546b74 refactor(08-03): gate forensic console.* and delete noise in timezoneUtils
DIR-01 progress (Task 2 of 4). 5 console.* sites in timezoneUtils.ts:
- GATE (2): invalid timezone warn (215), catastrophic TZ conversion error (224)
- DELETE (3): toJSDate-failed warn paths (179, 200) and convertTimezone
  invalid-zone warn (266) — all fall back silently

Per-file const DEBUG = false at top; each gated site has per-line
eslint-disable-next-line no-console -- DEBUG flag (Phase 8 D-07).

Adjacent cleanup: deleted catch (error) bindings became catch {} where
the binding was solely the deleted console.* argument (matches Wave 1
catch {} convention from D-09). MemoChron: prefix added to the two
gated logs per CONVENTIONS.md §Logging.
2026-05-17 09:43:45 +03:00
formax68
4093f7b582 refactor(08-03): gate forensic console.* and delete noise in CalendarService
DIR-01 progress (Task 1 of 4). 14 console.* sites in CalendarService.ts:
- GATE (4): cache miss (302), non-403/404 HTTP error, fetch catch, Outlook HTML
- DELETE (10): no-enabled-sources, fetch catch wrapper, background refresh
  lifecycle, cache save log/error, 403/404 (Notice-paired), invalid data
  (Notice-paired), local file read error, platform info debug

Per-file const DEBUG = false at top; each gated site has per-line
eslint-disable-next-line no-console -- DEBUG flag (Phase 8 D-07).

Adjacent cleanup (caused by deletions):
- Removed orphaned logPlatformInfo() method and its call site (function body
  was solely the deleted console.debug)
- Removed unused Platform import (only used by the deleted function)
- Outer fetchCalendars catch now catch-less (error binding became unused
  after console.error deletion; matches Wave 1's catch {} convention per D-09)
2026-05-17 09:42:42 +03:00
formax68
0676ad5869 docs(phase-08): update tracking after wave 2 2026-05-17 09:37:34 +03:00
formax68
3e1c09a33b chore: merge executor worktree (worktree-agent-a613acdbe3d460fca) 2026-05-17 09:37:22 +03:00
formax68
3133d4e4fc docs(08-02): summary for DIR-09 type hygiene cleanup
Plan 08-02 closed 18 DIR-09 violations across 10 files in three atomic
commits (413b6f3, e69c2fa, acf4626). Amendments A1 (typed moment import)
and A2 (getValues tightening) both applied. No executable ??-with-constant
LHS violations found in src/.
2026-05-17 09:36:54 +03:00
formax68
acf46265b9 refactor(08-02): fix no-case-declarations and no-useless-escape (DIR-09)
- pathUtils.ts:47 — wrap case PathType.FILE_URL body in { ... } block scope
  (the let normalized declaration leaked across cases without braces)
- viewRenderers.ts:370 — drop unnecessary backslash inside regex character
  class: [-\/] -> [-/] (slash does not need escaping inside [...])

Nullish-coalescing audit: grep -rnE '\b(null|undefined|"")\s*\?\?' src/
returned only the documentation-comment hit at SettingsTab.ts:262. No
executable violations.
2026-05-17 09:34:58 +03:00
formax68
e69c2fa194 refactor(08-02): replace (window as any).moment with typed obsidian import (A1)
Per Amendment A1, the 5 (window as any).moment casts get replaced with the
typed import { moment } from "obsidian" (obsidian.d.ts exports moment as
typeof Moment). Removes 5 dead null-check branches that existed only because
the cast was treated as nullable: 4 negative-shape (if (!moment) return) and
1 positive-shape (if (moment) { weekNum = ... } flattened to unconditional).

- CalendarView.ts: 3 sites (checkDailyNoteForDate, renderWeekNumber,
  handleDailyNoteClick) — adds moment to existing obsidian import
- EmbeddedCalendarView.ts: 1 site — adds moment to existing obsidian import
- EmbeddedAgendaView.ts: 1 site — adds moment to existing obsidian import
2026-05-17 09:34:08 +03:00
formax68
413b6f3bfc refactor(08-02): tighten ical.d.ts shim and fix 4 non-ambient any sites
- ical.d.ts: getValues() return tightened to Array<Time | Duration |
  string> (Amendment A2); add Property.jCal: unknown[] to codify the
  internal access used at CalendarService.ts:940 and IcsImportService.ts:101
- eslint.config.mjs: add **/*.d.ts no-explicit-any: off exclusion (D-08)
- CalendarService.ts:317 — isValidCache(cache: unknown) with the
  canonical narrowing from RESEARCH.md Pitfall 3 (Record<string, unknown>
  intermediate + typeof/Array.isArray checks)
- CalendarService.ts:771 — forEach((value: Time | Duration | string))
  via tightened getValues(); narrow via value instanceof Time
- CalendarService.ts:940 — (dtstart as any).jCal -> dtstart.jCal via shim
- IcsImportService.ts:101 — same
- SettingsTab.ts:1180 — generatePreviewPath(event: Pick<CalendarEvent,
  'title' | 'start' | 'end' | 'source'>)
2026-05-17 09:32:23 +03:00
formax68
0d27d263b1 docs(phase-08): update tracking after wave 1 2026-05-16 18:07:35 +03:00
formax68
b8843261d9 chore: merge executor worktree (worktree-agent-a217a557a81785b8a) 2026-05-16 18:07:14 +03:00
formax68
99865a8903 docs(08-01): summary for unused vars cleanup plan
Records the 18 @typescript-eslint/no-unused-vars violations closed,
the two catch-binding conversions, per-symbol grep verifications,
and the two minor deviations (DEFAULT_CALENDAR_URLS export delete
in constants.ts; split into two atomic per-task commits per executor
protocol).
2026-05-16 18:06:48 +03:00
formax68
a557c10c68 refactor(08-01): remove unused vars in utils and views (Task 2)
Removes 10 of 18 @typescript-eslint/no-unused-vars violations:
- viewRenderers.ts:2 (MemoChronSettings import)
- viewRenderers.ts:3 (TFile, Notice, App imports)
- CalendarView.ts:1 (DropdownComponent import)
- CalendarView.ts:14 (DateElements interface)
- CalendarView.ts:200 (controls local var → bare call)
- CalendarView.ts:1101 (title local var → bare expression)
- EmbeddedCalendarView.ts:15 (CalendarEvent import)
- EmbeddedCalendarView.ts:109 (title local var → bare call)
2026-05-16 18:04:52 +03:00
formax68
c9625477e4 refactor(08-01): remove unused vars in services and settings (Task 1)
Removes 8 of 18 @typescript-eslint/no-unused-vars violations:
- CalendarService.ts:12 (convertTimezone import)
- CalendarService.ts:531 (unused error catch binding → catch {})
- IcsImportService.ts:5 (Property import)
- SettingsTab.ts:6 (TextAreaComponent import)
- SettingsTab.ts:7 (DropdownComponent import)
- SettingsTab.ts:16 (CalendarNotesSettings import)
- SettingsTab.ts:1174 (unused error catch binding → catch {})
- settings/types.ts:4 (DEFAULT_CALENDAR_URLS import)

Also removes the unused export at constants.ts:5 to satisfy the
plan acceptance criterion that grep -rn "DEFAULT_CALENDAR_URLS" src/
returns zero matches.

Catch bodies do not reference the error binding (per D-09 default).
2026-05-16 18:03:36 +03:00
formax68
bd397bf227 docs(08): commit phase research notes 2026-05-16 17:58:42 +03:00
formax68
f12a391a5a docs(08): create phase plan 2026-05-16 17:55:41 +03:00
formax68
5c9d6a4245 docs(08): add validation strategy 2026-05-16 17:26:45 +03:00
formax68
c2b91b9a07 docs(08): record post-research amendments to context 2026-05-16 17:25:59 +03:00
formax68
ea6953ad52 docs(state): record phase 8 context session 2026-05-16 17:08:32 +03:00
formax68
e50b0f3731 docs(08): capture phase context 2026-05-16 17:08:27 +03:00
formax68
edc3e12d61 docs(phase-07): evolve PROJECT.md after phase completion 2026-05-16 16:46:06 +03:00
formax68
6fbfbfe7b7 docs(phase-07): complete phase execution 2026-05-16 16:39:30 +03:00
formax68
15ea40286b docs(07): add code review report 2026-05-16 16:34:13 +03:00
formax68
3a25526048 docs(phase-07): update tracking after wave 7 2026-05-16 16:24:01 +03:00
formax68
9f7d3d37f3 docs(07-07): record BUG-07 closure summary and Phase 7 completion 2026-05-16 16:24:01 +03:00
formax68
fe21022b00 docs(07): close BUG-07 with Obsidian-side root cause note
Records BUG-07 closure with Obsidian-side root cause per CONTEXT D-12
step 3 outcome (b). UAT step 3 demonstrated asymmetric behavior: the
Settings modal stays open when MemoChron is disabled (amendment A1's
deletion of detachLeavesOfType from onunload eliminated that trigger),
but closes when MemoChron is re-enabled. The forum thread at
forum.obsidian.md/t/settings-modal-closes-when-disabling-a-plugins-actively-focused-view/111479
confirms the same modal-close reproduces with core plugins (graph view),
demonstrating the remaining trigger is in Obsidian core's
plugin-enable-while-view-focused code path, not in MemoChron.

A1 was the only plugin-side mitigation available — with detachLeavesOfType
removed, the plugin no longer explicitly tears down its workspace leaf on
disable, but Obsidian's automatic leaf cleanup during plugin enable still
runs and triggers the same modal-close path on re-enable. This cannot be
intercepted from plugin code.

07-HUMAN-UAT.md is updated to reference BUG-07-CLOSURE.md from step 3
Notes and to flip SC #5 to PASS (closure note recorded). Phase 7 is
fully complete with BUG-07 status closed-obsidian-side. Phase 8 (Type
Hygiene & Conventions / DOC-02) may begin.
2026-05-16 16:23:30 +03:00
formax68
67a77725a3 docs(phase-07): update tracking after wave 6 2026-05-16 16:21:51 +03:00
formax68
b6781f0653 docs(07-06): record Phase 7 UAT closure summary and BUG-07 hand-off 2026-05-16 16:21:47 +03:00