Skip to content

Capture: generate path locally + show pre-filled (don't hide behind 'vault auto-assigns') #126

Description

@unforced

Status

Scope reshaped 2026-05-13 after Aaron's design conversation. Original "pre-fill the path" issue evolved into a coherent capture-classification model. Note: notes#130 (merged) shipped the initial `quickPath()` pre-fill — this issue now covers the remaining reshape work: hierarchical tag-role defaults + idempotent schema setup. The full audit UI is split out to notes#129.

Design model

Path = organizational structure (where the file lives). Default: `Notes//` for ALL captures (text + audio). User can override per-capture or per-vault.

Tag = semantic classification (what the file IS). Default Tag Role values shift to hierarchical:

  • `captureText` → `capture/text` (with `parent_names: ["capture"]`)
  • `captureVoice` → `capture/voice` (with `parent_names: ["capture"]`)

Why capture/* not note/*: in vault, EVERY note is a note. Tagging one `#note` is tautological — adds no signal. `#capture` distinguishes notes-the-user-captured from imported / generated / derived ones. That's a real semantic axis. Plus your Tag Role keys already say "captureText"/"captureVoice" — the noun `capture` is already in the vocabulary.

Hierarchy via parent_names (vault feature, see `parachute-vault/core/src/notes.ts:425`):

  • `tag: "capture"` query → returns notes with `capture/text` OR `capture/voice` (descendants auto-expanded).
  • Future extensions like `capture/photo`, `capture/web-clip` slot in without renaming.

What to ship

  1. Update Tag Role defaults: captureTextcapture/text, captureVoicecapture/voice in `tag-roles.ts`.
  2. New file src/lib/vault/schema.ts declaring `NOTES_REQUIRED_SCHEMA`:
    export const NOTES_REQUIRED_SCHEMA = {
      tags: [
        { name: "capture", description: "Notes captured directly by user (text or voice)" },
        { name: "capture/text", parent_names: ["capture"], description: "Text capture" },
        { name: "capture/voice", parent_names: ["capture"], description: "Voice capture" },
      ],
    };
  3. Idempotent update-tag on first capture-per-role: when Capture saves a note with role-applied tag, ensure the parent + child exist with correct `parent_names`. Calls are idempotent — already-correct tags are no-ops.
  4. Existing vaults preserve their values: if user has `captureText = "quick"` (current default from rc.6), that stays. The schema-ensure call still ensures `capture` parent + children exist, but doesn't change their Tag Role choices.
  5. Fix path-collision concern (raised in notes#130 review): regenerate `quickPath()` on reset() when the operator hasn't manually edited the path. Two captures in the same second should produce distinct paths.

Not in scope

  • Full Settings audit UI + connect-time banner → notes#129.
  • Per-vault customization of path templates → notes#128 research scope.

Acceptance

  • New vault first capture: schema is auto-set up (`capture` parent + `capture/text` child with `parent_names`).
  • Existing vault first capture: Tag Role values respected; schema still ensures parents/children exist.
  • Hierarchical query works: a note tagged `capture/text` matches a query for `capture`.
  • Multi-capture-in-one-second produces distinct paths.
  • Tests cover all four cases.

Related

  • notes#130 — shipped initial `quickPath()` pre-fill (this reshape builds on it).
  • notes#129 — schema-ensure UI follow-up.
  • patterns#57 — surface-declares-required-schema pattern (this is the first instance).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions