|
| 1 | +# Spec: Note creation linked to specific day (#232) |
| 2 | + |
| 3 | +## Goal |
| 4 | + |
| 5 | +Allow users to prefix a temporal expression (weekday, offset, shortcut) before a note title in the `journal.note` input so the note is both stored under and linked from the target day's journal entry instead of today's. |
| 6 | + |
| 7 | +## Why now |
| 8 | + |
| 9 | +The #177 tokenizer (PR #231) already parses temporal prefixes from note input — `"mon SecurityCodeReview"` → `offset = next Monday, text = "SecurityCodeReview"`. Two call sites still ignore `input.offset` and hardcode today: `LoadNotes.loadWithPath` (where to inject the link) and `Parser.resolveNotePathForInput` (where to store the file). Both are one-line fixes. |
| 10 | + |
| 11 | +## In scope |
| 12 | + |
| 13 | +- Use `input.generateDate()` (which respects `offset` and `date`) instead of `new Date()` / `new Input(0)` in both call sites. |
| 14 | +- Supported temporal expressions: anything `parseInput` already resolves — weekday aliases (`mon`, `monday`, `di`…), relative offsets (`+1`, `-1`), shortcuts (`today`, `tomorrow`, `yesterday`). |
| 15 | +- Default (no temporal prefix): `offset = 0` → `generateDate()` = today → behaviour unchanged. |
| 16 | + |
| 17 | +## Out of scope |
| 18 | + |
| 19 | +- Week-number targets (`w23 SecurityCodeReview`) — notes path patterns don't use week numbers; linking a note to a weekly entry is a separate concern. |
| 20 | +- ISO date targets (`2026-06-15 SecurityCodeReview`) — uncommon in note titles; deferred. |
| 21 | +- Changes to note filename format or path pattern config keys. |
| 22 | +- Changes to `ShowNoteCommand.execute` — it already calls `parseInput` and passes the result to `LoadNotes`; no change needed there. |
| 23 | + |
| 24 | +## Acceptance criteria |
| 25 | + |
| 26 | +1. `parseInput("mon SecurityCodeReview")` → `offset = next Monday's offset`, `text = "SecurityCodeReview"`. (Already true from #177 — regression test in PR #231.) |
| 27 | +2. Typing `mon SecurityCodeReview` in `journal.note` input creates `SecurityCodeReview.md` stored under Monday's date directory (per `journal.patterns.notes.path`) and injects the link into Monday's journal entry, not today's. |
| 28 | +3. Typing `SecurityCodeReview` (no prefix) → link injected into today's entry, note stored today. No regression. |
| 29 | +4. Typing `+2 PrepareDemo` → link in day-after-tomorrow's entry. Offset generalises to all `parseInput`-supported expressions. |
| 30 | +5. Full test suite green. |
| 31 | + |
| 32 | +## Entities / contracts |
| 33 | + |
| 34 | +### `src/features/entries/load-note.ts` — `LoadNotes.loadWithPath` |
| 35 | + |
| 36 | +Current: |
| 37 | +```ts |
| 38 | +await this.ctrl.reader.loadEntryForInput(new J.Model.Input(0)) |
| 39 | +``` |
| 40 | + |
| 41 | +Fix — replace with an `Input` that carries the same offset/date as `this.input`: |
| 42 | +```ts |
| 43 | +const entryInput = new J.Model.Input(this.input.offset); |
| 44 | +entryInput.date = this.input.date; |
| 45 | +entryInput.scope = this.input.scope; |
| 46 | +await this.ctrl.reader.loadEntryForInput(entryInput) |
| 47 | +``` |
| 48 | + |
| 49 | +`Input.generateDate()` already resolves `date` (if set) first, then falls back to `new Date() + offset`. No new logic needed. |
| 50 | + |
| 51 | +### `src/journal/parser.ts` — `Parser.resolveNotePathForInput` |
| 52 | + |
| 53 | +Current (line 48): |
| 54 | +```ts |
| 55 | +const date = new Date(); |
| 56 | +``` |
| 57 | + |
| 58 | +Fix: |
| 59 | +```ts |
| 60 | +const date = input.generateDate(); |
| 61 | +``` |
| 62 | + |
| 63 | +No other changes in this function. `getNotesFilePattern` and `getResolvedNotesPath` already accept a `Date` parameter. |
| 64 | + |
| 65 | +## Constraints |
| 66 | + |
| 67 | +- `ShowNoteCommand` casts `parsedInput as J.Model.NoteInput`. `NoteInput` extends `Input`; the cast is safe because only `_path` is added by `NoteInput`, which remains `""` but is never used in the note-creation flow (path is resolved freshly by `resolveNotePathForInput`). |
| 68 | +- `input.offset = 0` is the default → `generateDate()` = today → existing behaviour unchanged. |
| 69 | +- No changes to `Input`, `NoteInput`, or `IConfiguration` interfaces. |
| 70 | + |
| 71 | +## Open questions |
| 72 | + |
| 73 | +None. |
| 74 | + |
| 75 | +## Related issues |
| 76 | + |
| 77 | +- Blocked by: #177 / PR #231 (tokenizer must land first — `parseInput` must return correct offset from temporal prefix) |
| 78 | +- Follow-on from: #149 (original feature request) |
0 commit comments