create-battle-plan 1.3.0 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/template/.claude/commands/good-morning.md +13 -0
- package/template/.claude/commands/wrap-up.md +36 -0
- package/template/CLAUDE.md +135 -240
- package/template/CLAUDE.md.backup-2026-05-11 +310 -0
- package/template/events-archive.yml +5 -0
- package/template/events.yml +5 -0
- package/template/tools/events/add.js +64 -0
- package/template/tools/events/archive.js +55 -0
- package/template/tools/events/due-for-gate.js +31 -0
- package/template/tools/events/lib/events.js +221 -0
- package/template/tools/events/migrate-from-csv.js +90 -0
- package/template/tools/events/upcoming.js +33 -0
- package/template/tools/tasks/render-today.js +25 -10
package/package.json
CHANGED
|
@@ -72,6 +72,18 @@ Run these in parallel:
|
|
|
72
72
|
|
|
73
73
|
The battle plan is your orientation layer — read it on demand, not by default. `docs/today.md` is what the user sees, so lead with that.
|
|
74
74
|
|
|
75
|
+
## Step 1.6: Events context-debt warning (silent unless overdue)
|
|
76
|
+
|
|
77
|
+
`events.yml` carries past events that haven't been gated yet (transcript / spawned-tasks / insight not captured). Wrap-up's Step 4.5d handles these — but if the user skipped it or no wrap-up ran, they accumulate as context-debt.
|
|
78
|
+
|
|
79
|
+
Run `node tools/events/due-for-gate.js --json` and check whether any returned event has `end || start < (now - 2 days)`. If so, surface in the briefing:
|
|
80
|
+
|
|
81
|
+
> ⚠️ **Context-debt: N past event(s) ungated >2d** — EVT-{id} {title} ({start date}). Run `/wrap-up` Step 4.5d to capture transcript + insights.
|
|
82
|
+
|
|
83
|
+
Don't walk the gate during good-morning — wrap-up is the right time for that. Just flag it so the user knows.
|
|
84
|
+
|
|
85
|
+
If no events are returned, or none are >2d old, this step is silent.
|
|
86
|
+
|
|
75
87
|
## Step 2: Present the Briefing
|
|
76
88
|
|
|
77
89
|
Print a compact morning report with these sections:
|
|
@@ -97,6 +109,7 @@ Pull all defined metrics from `metrics.yml`. If targets are defined in the battl
|
|
|
97
109
|
|
|
98
110
|
End with 2-3 short questions:
|
|
99
111
|
- "Anything happen since we last talked? Replies, updates, new info?"
|
|
112
|
+
- "Any new events to schedule? Calls, demos, meetings I should add to `events.yml`?" — if they name anything, call `node tools/events/add.js --title "..." --start "ISO" [--lead-id <id-if-any>] --source manual-chat`.
|
|
100
113
|
- If there are stale items (no progress for 2+ days), ask about them specifically
|
|
101
114
|
- If a key deliverable is outstanding, ask about it
|
|
102
115
|
|
|
@@ -64,6 +64,42 @@ Run `node tools/tasks/render-today.js --quiet` so today's surface reflects any c
|
|
|
64
64
|
|
|
65
65
|
If 4.5a/4.5b changed anything, list it in Step 5 ("Task hygiene: N closed via git-drift, M archived").
|
|
66
66
|
|
|
67
|
+
**4.5d — Events gate (REQUIRED when past events exist):**
|
|
68
|
+
|
|
69
|
+
`events.yml` is the single source of truth for time-based events (calls, demos, meetings). Past events that haven't been "gated" (transcript + insights + spawned tasks captured) accumulate as context-debt. This step cycles the user through each one so context lands in the right docs before the event is archived.
|
|
70
|
+
|
|
71
|
+
Run `node tools/events/due-for-gate.js --json` and parse. If empty, this step is silent — skip to Step 5.
|
|
72
|
+
|
|
73
|
+
For each event returned, walk the user through them one-by-one (ONE at a time, sequential — do NOT batch):
|
|
74
|
+
|
|
75
|
+
```
|
|
76
|
+
Gate EVT-{id} — {title} ({start HH:MM}, type={type})
|
|
77
|
+
[a] Transcript path? (drag/paste a file path, or "none" for no recording)
|
|
78
|
+
[b] Hypothesis impacts? (comma-separated like "H47, H49", or "none" — skip if your project has no hypothesis tracker)
|
|
79
|
+
[c] Tasks spawned? (free-text bullets; each becomes a `tools/tasks/add.js` call)
|
|
80
|
+
[d] Insight worth saving? (yes → append to the relevant cascade-target doc; no/skip otherwise)
|
|
81
|
+
[skip] ← leave gate open, will resurface tomorrow
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
**Apply each answer immediately:**
|
|
85
|
+
|
|
86
|
+
- (a) → If a path was provided, copy/symlink the raw transcript to `docs/archive/transcripts/<slug>-YYYY-MM-DD.<ext>` (save raw verbatim FIRST, then distill). Store the final path on the event's `transcript_path` field via the events lib:
|
|
87
|
+
```js
|
|
88
|
+
const E = require('./tools/events/lib/events');
|
|
89
|
+
const state = E.load();
|
|
90
|
+
E.upsert(state, { id: <id>, transcript_path: '<path>' });
|
|
91
|
+
E.save(state);
|
|
92
|
+
```
|
|
93
|
+
- (b) → For each `H{n}`, append a short `> **[UPDATE YYYY-MM-DD · Source: EVT-{id} {title}]**` block to `docs/validation/hypotheses.md` (or your equivalent) near the relevant hypothesis. Store the list in the event's `hypothesis_impacts` field via the events lib. Skip if no hypothesis tracker exists.
|
|
94
|
+
- (c) → For each task description, run `node tools/tasks/add.js "<title>" [--due ...] [--lane ...] [--priority ...]`. Capture returned `TASK-N` ids into the event's `spawned_tasks` field.
|
|
95
|
+
- (d) → Append a dated section to the relevant cascade-target doc (e.g. `docs/validation/external-insights.md` for conversation findings) using its `Compression: chronological` format: `## YYYY-MM-DD — <title>` heading.
|
|
96
|
+
- After ALL non-skipped answers applied → stamp `gate_completed_at` (ISO now) on the event via the events lib.
|
|
97
|
+
- If the user picked `[skip]` → leave `gate_completed_at` null; the event resurfaces in tomorrow's wrap-up.
|
|
98
|
+
|
|
99
|
+
**Outreach add-on (Profile B only):** if `outreach/leads.csv` exists, also ask `[e] Lead status change? (e.g. call_done → verbal, or call_done → dead; "none" if unchanged)`. Update `leads.csv` via the Node load-mutate-save pattern in `tools/outreach/lib/leads.js`, then `node tools/outreach/sync-metrics.js`.
|
|
100
|
+
|
|
101
|
+
**Finally:** run `node tools/events/archive.js`. Moves gated events (terminal status + `gate_completed_at` set) → `events-archive.yml`. Idempotent.
|
|
102
|
+
|
|
67
103
|
## Step 5: Report
|
|
68
104
|
|
|
69
105
|
Print:
|
package/template/CLAUDE.md
CHANGED
|
@@ -1,214 +1,171 @@
|
|
|
1
|
-
# Battle Plan —
|
|
1
|
+
# Battle Plan — Project Instructions
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
## How this project works — read this first
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
## Two-View Model — Read This First
|
|
8
|
-
|
|
9
|
-
**The cascade is your orientation layer. `docs/today.md` is the user's operating surface. The chat is the user's only UI.**
|
|
10
|
-
|
|
11
|
-
The user should never have to look at the cascade, the battle plan, `tasks.yml`, or any internal markdown to operate the system. The chat with you is the UI; the cascade is your memory; `docs/today.md` is a thin clickable surface in their editor for ticking through the day. Everything else exists for *you*, not them.
|
|
12
|
-
|
|
13
|
-
- **Your view (the cascade):** `docs/battle-plan.md` at the top, source docs below it, `metrics.yml` as numeric truth, `tasks.yml` as the structured task log. Narrative, deep, linked. You read and write this freely — it is how you reconstruct project state and cascade new information.
|
|
14
|
-
- **User's view:** `docs/today.md`, generated by `tools/tasks/render-today.js` from `tasks.yml`. Rendered in Obsidian Tasks plugin format — query blocks project pill-styled lists over a raw `## Task data` section at the bottom (lane-grouped within each priority bucket). The user checks boxes in Obsidian; `tools/tasks/flush-today.js` reconciles those edits back into `tasks.yml`. When they want deep context, they ask you in chat — you traverse the cascade on their behalf.
|
|
15
|
-
|
|
16
|
-
**Rules:**
|
|
17
|
-
- Never grow the battle plan's TL;DR into a wall of prose. Keep header blocks terse; append Daily Log entries chronologically.
|
|
18
|
-
- When the user drops new tasks, add them via `node tools/tasks/add.js "..." [--due YYYY-MM-DD] [--tag X] [--priority 1|2|3] [--lane LANE] [--implication PATH]`. Don't bury tasks in battle plan prose.
|
|
19
|
-
- After any task mutation (add, complete, snooze, triage), run `node tools/tasks/render-today.js` so `docs/today.md` stays fresh.
|
|
20
|
-
- `verify-cascade.sh` Check 6 confirms `today.md` is not stale relative to `tasks.yml`.
|
|
21
|
-
|
|
22
|
-
---
|
|
23
|
-
|
|
24
|
-
## Task Lanes — what goes where
|
|
5
|
+
Two views of the same project, and Claude operates across both.
|
|
25
6
|
|
|
26
|
-
|
|
7
|
+
**Claude's view (the cascade):** `docs/battle-plan.md` at the top, source docs below it (under `docs/`), `metrics.yml` as numeric truth, `events.yml` for time-based events, `tasks.yml` for strategic tasks. Narrative, deep, linked. Claude reads and writes this freely — it's how project state is reconstructed across sessions.
|
|
27
8
|
|
|
28
|
-
|
|
29
|
-
|---|---|
|
|
30
|
-
| `build` | Build, design, or document the product itself (MVP, demos, architecture, integrations) |
|
|
31
|
-
| `outreach` | Cold DMs / InMails / posts / templates / cold-email infra-as-pipeline |
|
|
32
|
-
| `discovery` | Chase or nurture a *named human relationship* — warm intros, follow-ups, scheduling specific calls |
|
|
33
|
-
| `infra` | Plumbing — DNS, GCP/AWS, deploy, env, secrets, cold-email domain warm-up |
|
|
34
|
-
| `fundraising` | Apply to or maintain relationships with accelerators / VCs / angels |
|
|
35
|
-
| `meta` | Doc/process work with no other natural lane (default fallback) |
|
|
36
|
-
|
|
37
|
-
**Adapt this set to your project.** Lanes are configurable in `tools/tasks/lib/tasks.js` (`VALID_LANES`) — when you change them, also update `tools/tasks/migrate-lanes.js` keyword buckets and the `LANE_DISPLAY` / `LANE_ORDER` tables in `tools/tasks/render-today.js`.
|
|
38
|
-
|
|
39
|
-
**Personalities don't get their own lane.** A specific advisor or co-founder's input flows into all the action lanes. A task like "ask <advisor> about X" is `discovery` (relationship), `build` (product feedback), or `meta` (process), depending on what *closing* the task produces.
|
|
9
|
+
**User's view:** `docs/today.md` — generated by `tools/tasks/render-today.js` from `tasks.yml`, rendered in Obsidian Tasks plugin format (query blocks projecting pill-styled lists over a raw `## Task data` section at the bottom, lane-grouped within each priority bucket). The user checks boxes in Obsidian; `tools/tasks/flush-today.js` reconciles those edits back into `tasks.yml`. Their other primary surface is this chat — when they want deep context, they ask, and Claude traverses the cascade on their behalf.
|
|
40
10
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
`tasks.yml` is for **ad-hoc strategic / build / discovery-protocol / high-stakes individual conversations.** Examples: a milestone call with a specific stakeholder where multiple people join; a piece of pitch copy that needs to be written by a specific date; a load-bearing architecture decision that gates other work.
|
|
44
|
-
|
|
45
|
-
Routine lead-by-name follow-ups ("X accepted, send DM") belong in the **outreach blitz pipeline**, not in `tasks.yml`. The blitz already surfaces those through `daily-targets.js` + `leads.csv` flags + accepted-not-replied detection on timers. Don't duplicate that work as tasks.
|
|
46
|
-
|
|
47
|
-
When uncertain, default to the blitz. `tasks.yml` is a journal of strategic intent, not a worklist.
|
|
11
|
+
**Core principle:** the user should never have to look at the cascade, the battle plan, `tasks.yml`, `events.yml`, or any internal markdown to operate the system. The chat with Claude is the UI; the cascade is Claude's memory; `docs/today.md` is a thin clickable surface for ticking through the day. Everything else exists for Claude, not them.
|
|
48
12
|
|
|
49
13
|
---
|
|
50
14
|
|
|
51
|
-
##
|
|
52
|
-
|
|
53
|
-
Run weekly to keep `tasks.yml` honest. The skill (`.claude/commands/weekly-triage.md`) walks the user through every open task one at a time using `AskUserQuestion`'s arrow-key UI. Each decision (`done` / `snooze N` / `demote` / `merge X` / `delete` / `lane LANE` / `priority N` / `keep`) is applied to `tasks.yml` immediately — no batching.
|
|
15
|
+
## The Cascade — the core protocol
|
|
54
16
|
|
|
55
|
-
|
|
17
|
+
**Trigger:** any information shared in chat (or surfaced from tool output) that affects project state. This includes:
|
|
18
|
+
- Conversations, calls, or meetings (any signal — positive, negative, ambiguous)
|
|
19
|
+
- Research findings (desk research, web search, competitor intel)
|
|
20
|
+
- New targets, contacts, or refinements
|
|
21
|
+
- Metric changes
|
|
22
|
+
- Information that validates, invalidates, or adds nuance to a hypothesis
|
|
23
|
+
- New time-based events (calls, demos, meetings, anything with a start datetime + counterparty)
|
|
24
|
+
- Outreach activity (if the outreach add-on is installed — Profile B)
|
|
56
25
|
|
|
57
|
-
|
|
58
|
-
- **`tools/tasks/triage-due.js`** — lightweight SessionStart-hook nudge. Silent unless one of three thresholds trips: time-based (≥7d since last triage), stale-task (≥20 open tasks ≥14d old), or volume (≥60 open). Wired in `.claude/settings.json`. The skill stamps `last_triage_at` in `tasks.yml` on completion to suppress the nudge until the next cycle.
|
|
26
|
+
When triggered, update top-down in this exact order. Each step depends on the one above it. Never skip.
|
|
59
27
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
28
|
+
```
|
|
29
|
+
Step 0: raw state changes → metrics.yml / tasks.yml / events.yml / (leads.csv if Profile B)
|
|
30
|
+
↓
|
|
31
|
+
Step 1: docs/battle-plan.md ← TL;DR + Key Metrics table + Daily Log entry
|
|
32
|
+
↓
|
|
33
|
+
Step 2: source docs (only the relevant ones):
|
|
34
|
+
├── docs/validation/external-insights.md ← conversations & meetings (chronological)
|
|
35
|
+
├── docs/validation/hypotheses.md ← validation/invalidation (amended)
|
|
36
|
+
├── docs/market/ ← persona / strategy / competitive intel
|
|
37
|
+
├── docs/research/ ← foundational knowledge
|
|
38
|
+
└── (any other domain docs you've added)
|
|
39
|
+
↓
|
|
40
|
+
Step 3: tools/touch-date.sh ← stamp Last Updated on every modified file
|
|
41
|
+
↓
|
|
42
|
+
Step 4: tools/verify-cascade.sh ← verify TL;DR / metrics / dates / today.md staleness
|
|
43
|
+
```
|
|
67
44
|
|
|
68
|
-
|
|
45
|
+
If `outreach/leads.csv` exists (Profile B — outreach add-on), Step 0 also covers leads.csv mutations, and `sync-metrics.js` auto-chains from every `flush-*.js` script (it derives `metrics.yml` from the CSV — never hand-edit metrics directly).
|
|
69
46
|
|
|
70
|
-
|
|
71
|
-
-
|
|
72
|
-
-
|
|
73
|
-
-
|
|
74
|
-
- `
|
|
47
|
+
**Sources of truth — one per concept, no parallel stores:**
|
|
48
|
+
- `metrics.yml` — every metric (derived from leads.csv when outreach is installed; hand-edited otherwise)
|
|
49
|
+
- `events.yml` / `events-archive.yml` — every time-based event
|
|
50
|
+
- `tasks.yml` — every strategic / build / milestone task
|
|
51
|
+
- `docs/battle-plan.md` — current state ("where are we right now")
|
|
52
|
+
- `outreach/leads.csv` (Profile B only) — every lead
|
|
75
53
|
|
|
76
|
-
|
|
54
|
+
Never put state in markdown tables that lives somewhere structured. Never create a parallel store.
|
|
77
55
|
|
|
78
56
|
---
|
|
79
57
|
|
|
80
|
-
##
|
|
81
|
-
|
|
82
|
-
`tasks.yml` is append-only by design (audit trail), but it shouldn't grow forever. The archive script moves any `status: done|cancelled` row with `done_at < today - 14d` into `tasks-archive.yaml` (created on first run, same schema, sorted by `done_at` ascending).
|
|
83
|
-
|
|
84
|
-
- **Default retention:** 14 days. Pass `--days N` to override, or `--all` to archive every closed row regardless of age.
|
|
85
|
-
- **Idempotent:** dedups by `id` against the existing archive. Safe to run on every `/wrap-up`.
|
|
86
|
-
- **Wired into `/wrap-up` Step 4.5b** — runs daily as part of end-of-day routine.
|
|
87
|
-
- **Backfill safety:** closed rows missing `done_at` get stamped today and kept one cycle (so a date-less row doesn't get archived without chronological position).
|
|
88
|
-
- **Re-importing a task:** intentional friction. Manually move the row from `tasks-archive.yaml` → `tasks.yml` and set `status: open`.
|
|
89
|
-
|
|
90
|
-
---
|
|
58
|
+
## Behavioral rules — when X happens, do Y
|
|
91
59
|
|
|
92
|
-
|
|
60
|
+
**When the user mentions a time-based event** ("demo with X Thursday 2pm", "advisor call Friday 10am", "dentist Monday 9am"): call `node tools/events/add.js --title "..." --start "ISO" [--lead-id <id>] [--attendee "X"] [--type ...]`. Two criteria for an event (both required): a start datetime AND a counterparty/attendee. Anything failing either stays in `tasks.yml`.
|
|
93
61
|
|
|
94
|
-
**
|
|
62
|
+
**When the user drops a transcript** (paste, file path, attachment): save the raw verbatim file FIRST to `docs/archive/transcripts/<slug>-YYYY-MM-DD.<ext>`. Do not rewrite, summarize, or trim. THEN distill into the appropriate cascade-target doc. Always link back: `_Raw transcript: [path](...)._` Never delete transcripts — they're immutable audit trail.
|
|
95
63
|
|
|
96
|
-
When
|
|
64
|
+
**When the user drops new tasks:** add via `node tools/tasks/add.js "..." --lane LANE [--due ...] [--tag ...] [--priority 1|2|3] [--implication PATH] [--blocked-by N]`. `--lane` is required (one of: `build` / `outreach` / `discovery` / `infra` / `fundraising` / `meta` — customize in `tools/tasks/lib/tasks.js`). After any task mutation, run `node tools/tasks/render-today.js` so `docs/today.md` stays fresh.
|
|
97
65
|
|
|
98
|
-
|
|
99
|
-
|
|
66
|
+
**When a number from one doc appears in another:** annotate as a markdown link.
|
|
67
|
+
- Tier 1 — numbers in `metrics.yml`: `[**42**](metrics.yml#outreach_sent)`
|
|
68
|
+
- Tier 2 — numbers from another doc: `[**60%**](external-insights.md#session-2) of time on evidence`
|
|
100
69
|
|
|
101
|
-
|
|
102
|
-
- Update the **TL;DR** with current status
|
|
103
|
-
- Update the **Key Metrics** table (numbers reference metrics.yml)
|
|
104
|
-
- Update **Today's Priorities** if relevant
|
|
105
|
-
- Append to **Daily Log** for today
|
|
70
|
+
Numbers native to a doc (where they originate) have no annotation. Verified by `tools/check-metrics.sh`.
|
|
106
71
|
|
|
107
|
-
|
|
108
|
-
Update only the docs relevant to the new information. Route new info to the appropriate domain doc under `docs/`. Common patterns:
|
|
72
|
+
**When stating a claim:** mark its confidence — `Unvalidated` / `Soft signal` / `Practitioner-validated` / `Data-validated`. Include the source.
|
|
109
73
|
|
|
110
|
-
|
|
111
|
-
|-----------|------------|
|
|
112
|
-
| Conversation, call, or meeting | `docs/external-insights.md` — append as new dated session |
|
|
113
|
-
| Evidence for/against a hypothesis | The relevant domain doc — amend the claim with an `[UPDATE]` block |
|
|
114
|
-
| Outreach sent/received | The relevant market or sales doc — update tracking tables |
|
|
115
|
-
| Competitor intel | The relevant strategy or market doc |
|
|
116
|
-
| New foundational knowledge | The relevant research or domain doc |
|
|
74
|
+
**When `verify-cascade.sh` reports an issue:** fix it before ending the turn. Don't ship a known-stale state.
|
|
117
75
|
|
|
118
|
-
|
|
76
|
+
### Outreach add-on (Profile B only — when `outreach/leads.csv` exists)
|
|
119
77
|
|
|
120
|
-
|
|
121
|
-
Run `tools/touch-date.sh` on every file you modified in this session:
|
|
78
|
+
**When the user mentions a lead** (reply, accept, call booked, status change, new contact, dead): update `leads.csv` — do not just acknowledge in chat. Options: drop a line into `outreach/inbox/updates.md` + `flush-updates.js` (Haiku-powered), or a Node one-liner. Then run the cascade.
|
|
122
79
|
|
|
123
|
-
|
|
124
|
-
tools/touch-date.sh docs/battle-plan.md docs/validation/hypotheses.md [etc.]
|
|
125
|
-
```
|
|
80
|
+
**When the user reports a routine lead-by-name follow-up** ("chase X", "second follow-up to Y"): do NOT add to `tasks.yml`. The blitz pipeline (`daily-targets.js`) rotates these automatically from `leads.csv` flags. `tasks.yml` is for strategic / milestone / multi-party work.
|
|
126
81
|
|
|
127
|
-
|
|
128
|
-
Run `tools/verify-cascade.sh` and fix any issues it reports:
|
|
82
|
+
**When the user drops names** ("did we already contact X?"): run `node tools/outreach/lookup.js "Name1, Name2, ..."` FIRST. Fuzzy-matches against `leads.csv` — prevents duplicates.
|
|
129
83
|
|
|
130
|
-
|
|
131
|
-
tools/verify-cascade.sh
|
|
132
|
-
```
|
|
84
|
+
**When the user asks for numbers** ("how many in X bucket?", "what's the funnel?"): run `node tools/outreach/stats.js` first. Live tally with template performance, weekly breakdown, channel split, FU template breakdown.
|
|
133
85
|
|
|
134
86
|
---
|
|
135
87
|
|
|
136
|
-
##
|
|
137
|
-
|
|
138
|
-
### Registry Metrics (Tier 1 — deterministic)
|
|
139
|
-
Numbers defined in `metrics.yml`. Reference as: `[**N**](metrics.yml#field_name)`
|
|
140
|
-
|
|
141
|
-
This renders as a bold clickable number. Example: `[**42**](metrics.yml#outreach_sent)`
|
|
142
|
-
|
|
143
|
-
These are verified by exact numeric comparison via `tools/check-metrics.sh`.
|
|
88
|
+
## Schemas & format
|
|
144
89
|
|
|
145
|
-
###
|
|
146
|
-
Less common numbers from another doc. Reference as: `[**N**](source-doc.md#section-slug)`
|
|
147
|
-
|
|
148
|
-
Example: `60% of time on evidence [**60**](external-insights.md#session-2-key-insights)`
|
|
149
|
-
|
|
150
|
-
**Rule:** Every number referenced from another document MUST include a source annotation. Only numbers native to a doc (where they originate) have no annotation.
|
|
151
|
-
|
|
152
|
-
---
|
|
153
|
-
|
|
154
|
-
## Document Format
|
|
155
|
-
|
|
156
|
-
Every doc in `docs/` must have this frontmatter:
|
|
90
|
+
### Document frontmatter (every doc in `docs/`)
|
|
157
91
|
|
|
158
92
|
```markdown
|
|
159
93
|
# Document Title
|
|
160
94
|
|
|
161
|
-
**Last Updated:**
|
|
95
|
+
**Last Updated:** YYYY-MM-DD
|
|
162
96
|
**Status:** Active | Draft | Archived
|
|
163
97
|
**Role:** source-of-truth | cascade-target
|
|
164
98
|
**Compression:** chronological | amended | none
|
|
165
99
|
|
|
166
|
-
**TL;DR:** One paragraph
|
|
167
|
-
|
|
168
|
-
---
|
|
100
|
+
**TL;DR:** One paragraph with key numbers and source references.
|
|
169
101
|
```
|
|
170
102
|
|
|
171
|
-
-
|
|
172
|
-
-
|
|
173
|
-
-
|
|
174
|
-
-
|
|
175
|
-
- **TL;DR** must exist and contain all key metrics that appear in the doc.
|
|
176
|
-
|
|
177
|
-
---
|
|
178
|
-
|
|
179
|
-
## Compression Modes & Timestamping Rules
|
|
180
|
-
|
|
181
|
-
Every doc declares a `Compression:` mode in frontmatter. This tells the `/distill` command (and humans) how new info gets added to the doc and how old info gets compressed when it grows too long. The mode IS the timestamping rule for new info.
|
|
182
|
-
|
|
183
|
-
### `Compression: chronological`
|
|
184
|
-
The doc is an append-only log of dated entries. Each new piece of info goes in a new dated section.
|
|
103
|
+
- `Last Updated` must match today's date on any file modified in the current session.
|
|
104
|
+
- `Status` — `Active` = live; `Draft` = WIP; `Archived` = excluded from cascade.
|
|
105
|
+
- `Role` — `source-of-truth` = authoritative for its numbers. `cascade-target` = references numbers from elsewhere.
|
|
106
|
+
- `TL;DR` contains all key metrics that appear in the doc.
|
|
185
107
|
|
|
186
|
-
|
|
187
|
-
- **Examples:** `docs/battle-plan.md` (daily log), `docs/validation/external-insights.md` (conversation journal).
|
|
188
|
-
- **`/distill` behavior:** keeps the N most recent dated sections verbatim, archives the rest into `docs/archive/<same-path>`, replaces them with a thorough summary.
|
|
108
|
+
### Compression modes (drives `/distill`)
|
|
189
109
|
|
|
190
|
-
|
|
191
|
-
|
|
110
|
+
| Mode | Doc type | Timestamp rule for new entries |
|
|
111
|
+
|---|---|---|
|
|
112
|
+
| `chronological` | append-only log (battle-plan.md, external-insights.md) | every entry MUST start with a dated heading: `## YYYY-MM-DD — <title>` or `## Session N (YYYY-MM-DD) — <title>` |
|
|
113
|
+
| `amended` | living reference (hypotheses.md, icp-and-targets.md, competitive-landscape.md) | every revision MUST be a `> **[UPDATE YYYY-MM-DD · Source: ...]**` block placed immediately above the claim it modifies |
|
|
114
|
+
| `none` | static thesis (product-thesis.md, domain-101.md) | none — rewrite, don't amend. Git history is the timeline. `/distill` refuses to run. |
|
|
192
115
|
|
|
193
|
-
|
|
194
|
-
- **Examples:** `docs/validation/hypotheses.md`, `docs/market/icp-and-targets.md`, `docs/market/competitive-landscape.md`.
|
|
195
|
-
- **`/distill` behavior:** collapses old `[UPDATE]` blocks into the body text (preserving their content as integrated current-state), archives the raw blocks verbatim. Keeps the N most recent amendments per section inline.
|
|
116
|
+
Skipping the timestamp on a new entry in a `chronological` or `amended` doc is a bug — it gets silently absorbed into the wrong era during distillation.
|
|
196
117
|
|
|
197
|
-
### `
|
|
198
|
-
The doc is a static thesis or reference. It gets rewritten, not amended. Git history is the timeline.
|
|
118
|
+
### `tasks.yml` — task lanes
|
|
199
119
|
|
|
200
|
-
|
|
201
|
-
- **Examples:** `docs/strategy/product-thesis.md`, `docs/research/domain-101.md`.
|
|
202
|
-
- **`/distill` behavior:** refuses to run. If a `none` doc has grown unwieldy, rewrite it manually or change its `Compression:` mode first.
|
|
120
|
+
Every task has a `lane` (groups by *primary action*, not topic). Default vocabulary (customize in `tools/tasks/lib/tasks.js`):
|
|
203
121
|
|
|
204
|
-
|
|
205
|
-
|
|
122
|
+
| Lane | Primary action |
|
|
123
|
+
|---|---|
|
|
124
|
+
| `build` | Build, design, or document the product itself |
|
|
125
|
+
| `outreach` | Cold DMs / InMails / templates / cold-email infra |
|
|
126
|
+
| `discovery` | Chase or nurture a named human relationship |
|
|
127
|
+
| `infra` | Plumbing — DNS, GCP/AWS, deploy, env, secrets |
|
|
128
|
+
| `fundraising` | Accelerator / VC / angel relationships |
|
|
129
|
+
| `meta` | Doc/process work with no other natural lane (default fallback) |
|
|
206
130
|
|
|
207
|
-
|
|
131
|
+
Tasks may carry:
|
|
132
|
+
- `due: YYYY-MM-DD` — deadline (sorted to top by date).
|
|
133
|
+
- `priority: 1|2|3` — Today / This week / Backlog.
|
|
134
|
+
- `implications: [docs/path-a.md, ...]` — docs that should change when the task closes. `triage.js` flags drift when a linked doc's last commit predates the task.
|
|
135
|
+
- `blocked_by: [TASK-IDs]` — tasks that must close first. `render-today.js` emits the marker only for *still-open* blockers.
|
|
136
|
+
|
|
137
|
+
**Strategic vs routine:** `tasks.yml` is for strategic / multi-party / load-bearing work. Routine name-by-name follow-ups belong in the outreach blitz (Profile B), not here.
|
|
138
|
+
|
|
139
|
+
### `events.yml` — time-based events
|
|
140
|
+
|
|
141
|
+
Single source of truth for calls, demos, meetings, advisor sessions, dentist appointments, anything with a start datetime + counterparty.
|
|
142
|
+
|
|
143
|
+
- `events.yml` — future scheduled events.
|
|
144
|
+
- `events-archive.yml` — terminal events after the wrap-up gate has captured transcript / spawned tasks / insights.
|
|
145
|
+
|
|
146
|
+
```yaml
|
|
147
|
+
- id: 1
|
|
148
|
+
title: Demo v1 walkthrough — Counterparty / Company
|
|
149
|
+
start: "2026-05-14T14:00:00+02:00" # ISO 8601 with TZ
|
|
150
|
+
end: "2026-05-14T14:45:00+02:00"
|
|
151
|
+
type: demo # demo|discovery|investor|admin|personal|unspecified|other
|
|
152
|
+
status: scheduled # scheduled|in_progress|done|cancelled|no_show|rescheduled
|
|
153
|
+
attendees: [Counterparty, Me]
|
|
154
|
+
lead_id: https://www.linkedin.com/in/example # nullable (links to leads.csv if Profile B)
|
|
155
|
+
location: Google Meet
|
|
156
|
+
notes: free-form
|
|
157
|
+
source: manual-chat # manual-chat|flush-updates|migrate-from-csv|hand-edit
|
|
158
|
+
created_at: "2026-05-11T10:38:00.372Z"
|
|
159
|
+
# populated by the wrap-up gate after the event ends:
|
|
160
|
+
transcript_path: docs/archive/transcripts/...
|
|
161
|
+
spawned_tasks: [TASK-86, TASK-87]
|
|
162
|
+
hypothesis_impacts: [H47, H49]
|
|
163
|
+
gate_completed_at: "2026-05-14T16:30:00+02:00"
|
|
164
|
+
```
|
|
208
165
|
|
|
209
|
-
|
|
166
|
+
Lifecycle: `scheduled` → `done` → `gated` (wrap-up Step 4.5d fills `gate_completed_at`) → archived (`tools/events/archive.js` moves to events-archive.yml). Personal events (gym, dentist) can carry `type: personal` and skip the gate.
|
|
210
167
|
|
|
211
|
-
|
|
168
|
+
### Vault rules
|
|
212
169
|
|
|
213
170
|
1. **Update, don't duplicate.** Amend with `> **[UPDATE YYYY-MM-DD · Source: ...]**`
|
|
214
171
|
2. **Cross-link everything.** Claims reference their source doc.
|
|
@@ -216,95 +173,33 @@ When in doubt about which mode a new doc should use: chronological logs choose `
|
|
|
216
173
|
4. **Source everything.** Who said it, when, confidence level.
|
|
217
174
|
5. **Minimize file count.** Append, don't create new files.
|
|
218
175
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
## The `/wrap-up` Protocol
|
|
222
|
-
|
|
223
|
-
When the user says `/wrap-up`, run this end-of-day sequence:
|
|
224
|
-
|
|
225
|
-
**Step 1 — Scan:** Read the battle plan. Identify all tasks for today. Categorize: done, partially done, not started, new.
|
|
176
|
+
### Outreach `leads.csv` — Profile B only
|
|
226
177
|
|
|
227
|
-
|
|
178
|
+
If `outreach/leads.csv` exists in the project, the outreach add-on is active. See `outreach/README.md` for setup. `leads.csv` is the single source of truth for outreach metrics — `metrics.yml` is derived from it via `sync-metrics.js` (auto-chained from every `flush-*.js`).
|
|
228
179
|
|
|
229
|
-
|
|
180
|
+
Key columns (full HEADERS list in `tools/outreach/lib/leads.js`): `linkedin_url`, `first_name`, `last_name`, `title`, `company`, `country`, `email`, `source`, `tags`, `status`, `priority`, `contacted_at`, `replied_at`, `followed_up_at`, `channel`, `template`, `inmail_template`, `followup_template`, `notes`.
|
|
230
181
|
|
|
231
|
-
|
|
182
|
+
Status flow: `new → dm_sent → replied → call_booked → call_done → verbal → loi → paying`. Branches: `dead`, `withdrawn`.
|
|
232
183
|
|
|
233
|
-
|
|
234
|
-
- Metrics changed today (before → after)
|
|
235
|
-
- Docs updated
|
|
236
|
-
- Verification warnings (if any)
|
|
237
|
-
- Tomorrow's top priorities
|
|
238
|
-
|
|
239
|
-
**Step 6 — Commit:** Ask: "Want me to commit today's updates?" If yes, commit with message: `eod YYYY-MM-DD: [summary]`
|
|
184
|
+
Tags grow forward with `, ` separator. Notes grow forward with `| ` separator — never overwrite.
|
|
240
185
|
|
|
241
186
|
---
|
|
242
187
|
|
|
243
|
-
##
|
|
244
|
-
|
|
245
|
-
**Trigger:** If `outreach/leads.csv` exists in the project, the outreach system is active.
|
|
246
|
-
|
|
247
|
-
### Overview
|
|
248
|
-
|
|
249
|
-
The outreach system tracks a LinkedIn (or any channel) outreach pipeline through `outreach/leads.csv`. This CSV is the **single source of truth** for all outreach metrics — `metrics.yml` is derived from it, never edited directly for outreach numbers.
|
|
250
|
-
|
|
251
|
-
### First-Time Setup
|
|
252
|
-
|
|
253
|
-
If `outreach/leads.csv` exists but `.outreach-initialized` does NOT exist, read `outreach/README.md` and follow the Interactive Setup instructions to onboard the user.
|
|
254
|
-
|
|
255
|
-
### Daily Workflow Integration
|
|
256
|
-
|
|
257
|
-
The outreach system plugs into the cascade protocol:
|
|
258
|
-
|
|
259
|
-
1. User runs `node tools/outreach/daily-targets.js` → generates blitz checklist
|
|
260
|
-
2. User sends messages, ticks checkboxes
|
|
261
|
-
3. User runs `node tools/outreach/flush-targets.js` → updates leads.csv
|
|
262
|
-
4. `flush-targets.js` calls `sync-metrics.js` → derives metrics.yml from CSV
|
|
263
|
-
5. `sync-metrics.js` calls `update-dashboard.js` → regenerates mermaid dashboard
|
|
264
|
-
6. The cascade protocol takes over: metrics.yml → battle-plan.md → domain docs
|
|
265
|
-
|
|
266
|
-
### Scripts Reference
|
|
267
|
-
|
|
268
|
-
| Script | Purpose |
|
|
269
|
-
|--------|---------|
|
|
270
|
-
| `tools/outreach/daily-targets.js [N]` | Generate daily blitz checklist |
|
|
271
|
-
| `tools/outreach/flush-targets.js` | Process checked items from blitz |
|
|
272
|
-
| `tools/outreach/flush-updates.js` | Parse free-form natural language updates |
|
|
273
|
-
| `tools/outreach/flush-accepts.js` | Batch-process connection accepts |
|
|
274
|
-
| `tools/outreach/flush-inbox.js` | Add leads from manual URL list |
|
|
275
|
-
| `tools/outreach/sync-metrics.js` | Derive metrics.yml from leads.csv |
|
|
276
|
-
| `tools/outreach/update-dashboard.js` | Regenerate mermaid conversion dashboard |
|
|
277
|
-
| `tools/outreach/stats.js` | Print pipeline summary |
|
|
278
|
-
| `tools/outreach/lookup.js "Name"` | Fuzzy-search leads |
|
|
279
|
-
|
|
280
|
-
### Metrics Derivation
|
|
281
|
-
|
|
282
|
-
These metrics in `metrics.yml` are **derived** from leads.csv (never hand-edit):
|
|
283
|
-
|
|
284
|
-
- `outreach_sent` = leads with status past `new` or `contacted_at` set
|
|
285
|
-
- `responses` = `replied_at` set or status past `replied`
|
|
286
|
-
- `invitations_accepted` = leads tagged `accepted`
|
|
287
|
-
- `discovery_calls` = `call_at` in the past or status `call_done`
|
|
288
|
-
- `calls_booked` = status `call_booked` (snapshot)
|
|
289
|
-
- `verbal_commitments` = status `verbal`, `loi`, or `paying`
|
|
290
|
-
|
|
291
|
-
### Template System
|
|
292
|
-
|
|
293
|
-
Message templates live in `tools/outreach/templates.json`. The daily blitz assigns templates based on the `country_template_map` field (or round-robin if no mapping). Template performance (sent/accepted/replied/calls) is tracked automatically and displayed in the blitz checklist.
|
|
294
|
-
|
|
295
|
-
### Mermaid Dashboard
|
|
188
|
+
## Pointers
|
|
296
189
|
|
|
297
|
-
|
|
298
|
-
-
|
|
299
|
-
-
|
|
300
|
-
-
|
|
301
|
-
-
|
|
190
|
+
**Daily scripts:**
|
|
191
|
+
- `tools/tasks/` — task lifecycle: `add.js`, `render-today.js`, `flush-today.js`, `triage.js`, `archive.js`, `migrate-lanes.js`
|
|
192
|
+
- `tools/events/` — events lifecycle: `add.js`, `upcoming.js`, `due-for-gate.js`, `archive.js`, `migrate-from-csv.js`
|
|
193
|
+
- `tools/touch-date.sh` — stamp Last Updated in frontmatter
|
|
194
|
+
- `tools/verify-cascade.sh` — verify TL;DR / metrics / dates / today.md staleness
|
|
195
|
+
- `tools/check-metrics.sh` — verify Tier 1 metric link references
|
|
302
196
|
|
|
303
|
-
|
|
197
|
+
**Outreach scripts (Profile B):** `tools/outreach/` — `daily-targets.js`, `flush-targets.js`, `flush-updates.js`, `flush-accepts.js`, `flush-inbox.js`, `sync-metrics.js`, `update-dashboard.js`, `stats.js`, `lookup.js`, `stale-invitations.js`.
|
|
304
198
|
|
|
305
|
-
|
|
199
|
+
**Skills (`.claude/commands/`):**
|
|
200
|
+
- `good-morning` — morning standup (metrics + today.md + events context-debt check)
|
|
201
|
+
- `wrap-up` — end-of-day reconciliation + task hygiene + events gate
|
|
202
|
+
- `weekly-triage` — task-pile sweep
|
|
203
|
+
- `distill` — compress chronological / amended doc history
|
|
306
204
|
|
|
307
|
-
-
|
|
308
|
-
- **Different time horizon:** The system tracks weekly breakdowns — adjust `daily-targets.js` count parameter
|
|
309
|
-
- **Different channels:** The `channel` column supports any value (connection, inmail, email, etc.)
|
|
310
|
-
- **Different statuses:** Add to `VALID_STATUS` in `tools/outreach/lib/leads.js` and update derivation rules
|
|
205
|
+
**Auto-nudges:** `tools/tasks/triage-due.js` runs on every session start. When it prints a nudge, mention `/weekly-triage` to the user — do not auto-invoke.
|