--- name: motive description: Author and track a motive — a named, persistent work thread that outlives any single session. Captures an Objective, a charter with an open-items register (TBD/TBR), a compiled Decision Log, and named Baselines. Use for any initiative that spans multiple sessions or parallel agents. --- # groundwork:motive skill Use this skill when you are starting or continuing a multi-session work thread. A motive is the durable container for an initiative's objective, its open items, and the decisions and events that shaped it. It lives entirely in `.groundwork/motives//` (gitignored process state) and is separate from `doc/specs/`, which holds committed, public-facing outcome artifacts. Do NOT use this skill when: - You only need to resume where a session left off (use `groundwork:continue`). - You only need to hand off context to the next session (use `groundwork:handoff`). - You are writing a committed requirement or design document (use `groundwork:spec`). --- ## Vocabulary | Term | Meaning | |---|---| | **Motive** | A named work thread identified by a short `` (e.g. `plugin-cleanup`). Stored under `.groundwork/motives//`. | | **Objective** | A single sentence captured once when the motive is created. Never edited in place — superseded via a new decision if the goal shifts. | | **Charter** | The human-editable file at `.groundwork/motives//motive.md`. Contains the Objective, an Open Items register (TBD/TBR rows), and any standing context. The open-items register is the authoritative source for unresolved questions; do not track these anywhere else. | | **Open item** | A row in the charter's TBD/TBR register. Identified by an `id` (e.g. `TBD-2`). Resolved automatically when an `accepted` DECISION event carries `resolves: `. | | **Decision Log** | The compiled list of DECISION events for the motive. Generated by `journal compile`; never hand-edited. | | **Baseline** | A named snapshot pin — records the journal ordinal at the time of pinning so you can re-compile the motive's state as it was at that moment. | | **Ticket** | A durable work object under `.groundwork/motives//tickets/`. Filename convention: `NN-type-slug.md` — two-digit ordinal prefix, a closed type from `research`, `choose`, `model`, `build`, `grill`, `spec`, `fix`, `chore`, and a kebab-case slug (e.g. `01-research-auth-flow.md`). Hand or agent-authored; never auto-generated per ledger slice; never deleted or overwritten by groundwork tooling once created. Scaffold with `node hooks/motive-ticket.mjs create --type --slug --motive `; list with `motive-ticket list`; validate with `motive-ticket lint`. Carries sections: Question, Context, Evidence, Decision, Ruled out, Revisions, Links. Ledger slices reference tickets via `--ticket `. | | **tickets/** | The durable ticket store under the motive directory. Tooling only writes a ticket file when it does not already exist. Human edits are always preserved. | | **open-items/** | Generated drill-down views derived from open TBD/TBR items. This directory **is swept on regeneration** — anything placed here is overwritten. Do not store durable work objects here; use `tickets/` for those. | | **MAP.md** | Auto-regenerated human read path at `.groundwork/motives//MAP.md`. Renders from the ticket corpus with ledger status overlay. Never hand-edited; the regeneration cycle keeps it current. | --- ## Workflow ### 1. Create a motive ``` journal motive new --objective "One-sentence goal statement" ``` This creates `.groundwork/motives//motive.md` from the charter template and appends a `MOTIVE_CREATED` event carrying the objective. Running it again without `--force` exits 1 and leaves the existing charter intact; `--force` overwrites. ### 2. Edit the charter Open `.groundwork/motives//motive.md` directly. Add open items to the TBD/TBR register using the row format the template provides. Assign each item a stable `id` (e.g. `TBD-1`, `TBR-2`). The charter is human-first prose — write it as you would a working note, not a spec. ### 3. Append events All significant occurrences are recorded as typed journal events. The most important types: **Decision:** ``` journal append --motive --type DECISION --msg "Short human summary" \ --data '{"id":"D-1","decision":"Use X over Y","rationale":"X is faster and simpler","alternatives":["Y","Z"]}' ``` Required fields (exit 2 if any are absent): `id`, `decision`, `rationale`. Optional fields: `alternatives` (array of alternatives considered; defaults to `[]` when absent), `revises`, `supersedes`, `resolves`, `status`, `blast`, `research`. To refine an existing decision in place (same id, intentional update): ``` journal append --motive --type DECISION --msg "Refined: use X with caching" \ --data '{"id":"D-1","decision":"Use X with caching","rationale":"Updated after benchmarks","revises":"D-1"}' ``` Setting `data.revises` to the entry's own id (e.g. `"D-1"`) marks this as an intentional same-id refinement. The two events are merged into one compiled entry (earliest `ts` retained) and no collision warning is emitted. A `revises` value naming a different id does not suppress the collision flag. To supersede an existing decision with a new one (different id): ``` journal append --motive --type DECISION --msg "Accepted: use Z instead" \ --data '{"id":"D-2","decision":"Use Z","rationale":"Z is now supported","supersedes":"D-1","resolves":"TBD-3"}' ``` This marks D-1 `superseded` (with `superseded_by: D-2`) and resolves open item `TBD-3` if present in the charter. Both D-1 and D-2 appear as separate rows in the compiled output. A `rejected` decision does NOT resolve its `resolves` target. **Other useful event types** (all via `journal append --motive --type --msg "..."` with optional `--data`): | Type | When | |---|---| | `MILESTONE` | A major deliverable or phase boundary is reached | | `TASK_COMPLETE` | A concrete task within the initiative is done | | `GATE` | An advisor or external review has been passed | | `VERIFICATION` | A claim has been independently verified | | `HANDOFF` | Work is being handed to another agent or session | | `FAILURE` | A significant failure or regression occurred | | `SPEC_CHANGE` | A committed spec or doc was changed | | `WAIVER` | A constraint was explicitly waived with justification | ### 4. Pin a baseline When you reach a stable state you may want to return to later, pin it: ``` journal baseline --motive ``` Baseline names should be short and meaningful (e.g. `pre-deletion`, `wave-1-green`). Duplicate names are allowed — the latest write wins. ### 5. Compile Compile the motive's event stream into a versioned Markdown + JSON view: ``` journal compile ``` Common flags: | Flag | Effect | |---|---| | `--at ` | Fold only events up to a given ordinal or baseline name. Non-numeric names are resolved via `resolveBaseline`; unknown name → exit 2 with a list of known names. | | `--html` | Write an HTML dashboard alongside the `.json`/`.md` files under `.groundwork/compiled/`. | | `--tbd` | Print the open-items count line (warn-only; off by default). | | `--stdout` | Print without writing `.groundwork/compiled/` files. | | `--json` | Print only the JSON payload to stdout. | The Decision Log in the compiled output is derived from events — it is never hand-edited. To correct a decision, append a new event with the corrected status or a superseding decision. ### 6. Parallel sessions — claim a ledger slice before starting When multiple agents or sessions may work the same run ledger concurrently, claim the slice you intend to work before beginning: ``` ledger claim [ ...] ``` Flags: - `--json` — prints `{claimed, refused, ok}` for programmatic use. - `--strict` — exits non-zero if any id was refused (default is always exit 0). Claiming does not require `--token`. A slice already claimed by a different session is not overwritten; the command prints "already claimed by ``" and exits 0. A stale claim (from a session whose ledger is `active: false`) is reclaimable. Claims are automatically cleared when a slice reaches `complete` or `skipped`. --- ## Charter style The charter is human-first prose. A reader who has never seen the motive must understand any section cold — without opening another document. ### Open-items register Each entry follows a three-part shape: ``` - TBD-N: <1–3 sentences: why it matters and what is at stake, then the open question or direction> refs: · graduated-to: (where applicable) ``` - The first line is a complete sentence. No bare D-ids, file paths, or jargon as the opener. - The body leads with rationale (why it matters / impact), then the open question or direction. - Machine citations — D-ids, `file:line`, session ids — belong on the trailing `refs:` line, not inline in the prose. Inline id-chains make an entry unreadable cold. - No ALL-CAPS. No multi-deep decision-citation chains inline. ### Acceptance criteria One criterion per bullet; one complete human sentence per criterion. Enforcement detail (file paths, schema keys, hook names) belongs in a trailing `note:` line on that bullet, not embedded in the statement. ``` - AC-1: The open-items register displays a rationale body under every entry. note: enforced by motive-compile; see hooks/lib/motive-compile.mjs ``` ### Tickets pointer The charter does not duplicate the ticket list. Add a `## Tickets` section with a single pointer to `MAP.md` (the live auto-index); tooling keeps that file current. ```markdown ## Tickets See [MAP.md](MAP.md) for the live ticket index. ``` --- ## Negative scope - Motive state (`.groundwork/motives/`, `.groundwork/compiled/`) is gitignored process state. Do not commit it. - `doc/specs/` is the committed, public-facing outcome. Write specs there with `groundwork:spec`, not here. - The Decision Log is compiled output — never edit it directly. Corrections flow through new events. - The TBD gate (`--tbd`) is warn-only and off by default. It never blocks a session. - Claiming never rejects a session — it only reports and exits 0. - The HTML dashboard is a convenience view — it never gates any workflow step.