feat(lunatask): improve notes API

Amolith created

- GetNote: speculative implementation following existing patterns (API
may support it but undocumented)
- NotebookID: now optional in CreateNoteRequest per actual API behavior

Assisted-by: Claude Sonnet 4 via Crush

Change summary

lunatask/notes.go | 21 ++++++++++++++++-----
1 file changed, 16 insertions(+), 5 deletions(-)

Detailed changes

lunatask/notes.go 🔗

@@ -27,7 +27,7 @@ type Note struct {
 type CreateNoteRequest struct {
 	Name       *string `json:"name,omitempty"`
 	Content    *string `json:"content,omitempty"`
-	NotebookID string  `json:"notebook_id"`
+	NotebookID *string `json:"notebook_id,omitempty"`
 	Source     *string `json:"source,omitempty"`
 	SourceID   *string `json:"source_id,omitempty"`
 }
@@ -83,14 +83,25 @@ func (c *Client) ListNotes(ctx context.Context, opts *ListNotesOptions) ([]Note,
 	return resp.Notes, nil
 }
 
+// GetNote retrieves a specific note by ID.
+// Note: name and content fields are E2EE and will be null in the response.
+func (c *Client) GetNote(ctx context.Context, noteID string) (*Note, error) {
+	if noteID == "" {
+		return nil, fmt.Errorf("%w: note ID cannot be empty", ErrBadRequest)
+	}
+
+	resp, _, err := doJSON[noteResponse](c, ctx, http.MethodGet, "/notes/"+noteID, nil)
+	if err != nil {
+		return nil, err
+	}
+
+	return &resp.Note, nil
+}
+
 // CreateNote creates a new note in Lunatask.
 // Returns nil, nil if a matching note already exists in the same notebook
 // with the same source/source_id (HTTP 204).
 func (c *Client) CreateNote(ctx context.Context, note *CreateNoteRequest) (*Note, error) {
-	if note.NotebookID == "" {
-		return nil, fmt.Errorf("%w: notebook_id is required", ErrBadRequest)
-	}
-
 	resp, noContent, err := doJSON[noteResponse](c, ctx, http.MethodPost, "/notes", note)
 	if err != nil {
 		return nil, err