create-battle-plan 1.2.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/weekly-triage.md +93 -0
- package/template/.claude/commands/wrap-up.md +59 -0
- package/template/.claude/settings.json +14 -1
- package/template/CLAUDE.md +144 -179
- 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/add.js +43 -4
- package/template/tools/tasks/archive.js +194 -0
- package/template/tools/tasks/flush-today.js +6 -2
- package/template/tools/tasks/lib/tasks.js +18 -6
- package/template/tools/tasks/migrate-lanes.js +104 -0
- package/template/tools/tasks/render-today.js +110 -33
- package/template/tools/tasks/triage-due.js +74 -0
- package/template/tools/tasks/triage.js +302 -0
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
|
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Walk through every open task lane-by-lane with a multi-choice action menu. Closes stale items, merges duplicates, re-lanes mis-classified work. Stamps last_triage_at when done.
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Weekly Triage
|
|
6
|
+
|
|
7
|
+
Run this once a week to keep `tasks.yml` honest. The user clicks through each open task with arrow-key choices; you apply each decision to `tasks.yml` immediately.
|
|
8
|
+
|
|
9
|
+
## Step 0 — Anchor to real time
|
|
10
|
+
|
|
11
|
+
Run `date` to anchor today's date. Don't infer from session context.
|
|
12
|
+
|
|
13
|
+
## Step 1 — Gather state
|
|
14
|
+
|
|
15
|
+
Run `node tools/tasks/triage.js --json` and parse the output. Also run `git log --oneline -30` for context on recent commits.
|
|
16
|
+
|
|
17
|
+
## Step 2 — Briefing
|
|
18
|
+
|
|
19
|
+
Tell the user the headline numbers from the report's `stats` block:
|
|
20
|
+
|
|
21
|
+
- Total open
|
|
22
|
+
- Overdue
|
|
23
|
+
- Stale (≥ stale_threshold_days, not overdue)
|
|
24
|
+
- Distribution by lane
|
|
25
|
+
|
|
26
|
+
Surface anything notable: the worst overdue, the most stale lane, any drift flags.
|
|
27
|
+
|
|
28
|
+
Ask:
|
|
29
|
+
|
|
30
|
+
> Walk through lane-by-lane in order (build → outreach → discovery → infra → fundraising → meta), or start with a specific lane?
|
|
31
|
+
|
|
32
|
+
## Step 3 — Walk one task at a time
|
|
33
|
+
|
|
34
|
+
For each open task in the chosen order:
|
|
35
|
+
|
|
36
|
+
1. Show 3-4 lines: title, key flags, a one-line context snippet, and the script's `suggestion` if any.
|
|
37
|
+
2. Use `AskUserQuestion` with these standard options (label them concisely — these are the most common decisions):
|
|
38
|
+
- **Done** — task is complete
|
|
39
|
+
- **Snooze 7 days** — defer; resurfaces in a week
|
|
40
|
+
- **Demote** — drop priority by one
|
|
41
|
+
- **Merge into TASK-X** — kill this task, fold into another (ask for X)
|
|
42
|
+
3. The user can pick "Other" to type a custom action: `delete`, `promote`, `keep`, `lane <LANE>`, `priority <N>`, `snooze <N>` for a custom snooze window, etc.
|
|
43
|
+
|
|
44
|
+
**Pacing:** present **one task at a time**. If the user says "go faster" or "skip ahead", batch 3-5 per message. If they say "keep all of these", apply `keep` to the whole lane.
|
|
45
|
+
|
|
46
|
+
## Step 4 — Apply decisions immediately (no batching)
|
|
47
|
+
|
|
48
|
+
For each user choice, Edit `tasks.yml` right away. Map decisions:
|
|
49
|
+
|
|
50
|
+
| Choice | Field changes |
|
|
51
|
+
|---|---|
|
|
52
|
+
| `done` | `status: done`, `done_at: <today>` |
|
|
53
|
+
| `snooze N` | `status: snoozed`, `snoozed_until: <today + N days>` |
|
|
54
|
+
| `demote` | `priority: priority + 1` (capped at 3) |
|
|
55
|
+
| `promote` | `priority: priority - 1` (floored at 1) |
|
|
56
|
+
| `merge X` | `status: cancelled`, prepend `"Merged into TASK-X — <today>"` to context |
|
|
57
|
+
| `delete` | `status: cancelled`, prepend `"Deleted via triage <today>"` to context |
|
|
58
|
+
| `lane <LANE>` | `lane: <LANE>` (validate against VALID_LANES in lib/tasks.js) |
|
|
59
|
+
| `priority <N>` | `priority: <N>` |
|
|
60
|
+
| `keep` | no change |
|
|
61
|
+
|
|
62
|
+
The "Merge into X" action is high-leverage when triaging a long pile — collapse scattered concerns into a single owner with consolidated context.
|
|
63
|
+
|
|
64
|
+
## Step 5 — Wrap up
|
|
65
|
+
|
|
66
|
+
Three things, in order:
|
|
67
|
+
|
|
68
|
+
### 5a. Stamp `last_triage_at`
|
|
69
|
+
|
|
70
|
+
This suppresses the SessionStart triage-due nudge until the next cycle. Without this, the nudge keeps firing on every session start and becomes spam.
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
node -e "const t=require('./tools/tasks/lib/tasks'); const s=t.load(); s.last_triage_at='$(date +%Y-%m-%d)'; t.save(s);"
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### 5b. Regenerate today.md
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
node tools/tasks/render-today.js
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### 5c. Print summary
|
|
83
|
+
|
|
84
|
+
- Tasks closed: N
|
|
85
|
+
- Tasks snoozed: N
|
|
86
|
+
- Tasks merged: N
|
|
87
|
+
- Tasks re-laned: N
|
|
88
|
+
- Open tasks remaining: N (was N before)
|
|
89
|
+
- Implications-drift heads-up: list any tasks where the linked doc still hasn't moved and the user kept the task open
|
|
90
|
+
|
|
91
|
+
## Tone
|
|
92
|
+
|
|
93
|
+
Direct. Bounded decisions. Don't editorialize on each task — you're a UI, not a coach.
|
|
@@ -42,6 +42,64 @@ With all info gathered, run the full cascade from CLAUDE.md:
|
|
|
42
42
|
4. Run `tools/touch-date.sh` on every modified file
|
|
43
43
|
5. Run `tools/verify-cascade.sh` — fix any errors
|
|
44
44
|
|
|
45
|
+
## Step 4.5: Task hygiene — REQUIRED daily
|
|
46
|
+
|
|
47
|
+
This step keeps `tasks.yml` honest. Run before regenerating `today.md` so any closures land in the day's surface.
|
|
48
|
+
|
|
49
|
+
**4.5a — Detect drift (tasks that should be closed but aren't):**
|
|
50
|
+
|
|
51
|
+
Run `node tools/tasks/triage.js --json` and scan the output for any open task with non-empty `recent_commits` (commits mentioning `TASK-N` since the task was created). For each:
|
|
52
|
+
- Surface to the user: "TASK-{id} ({title}) — recent commit '{subject}' suggests it's done. Mark closed?"
|
|
53
|
+
- If yes → set `status: done`, `done_at: <today>` via Edit on `tasks.yml`. If no → leave it.
|
|
54
|
+
|
|
55
|
+
Also surface any open task with `implications_drift` flagged (linked doc untouched since task created) — the user may have closed the work without updating the doc, OR the doc work is genuinely pending.
|
|
56
|
+
|
|
57
|
+
**4.5b — Archive old closed tasks:**
|
|
58
|
+
|
|
59
|
+
Run `node tools/tasks/archive.js`. This moves any `status: done|cancelled` row with `done_at < today - 14d` into `tasks-archive.yaml` (created on first run). Idempotent. Default retention = 14 days; pass `--days N` to override or `--all` to archive everything closed.
|
|
60
|
+
|
|
61
|
+
**4.5c — Regenerate today.md:**
|
|
62
|
+
|
|
63
|
+
Run `node tools/tasks/render-today.js --quiet` so today's surface reflects any closures from 4.5a.
|
|
64
|
+
|
|
65
|
+
If 4.5a/4.5b changed anything, list it in Step 5 ("Task hygiene: N closed via git-drift, M archived").
|
|
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
|
+
|
|
45
103
|
## Step 5: Report
|
|
46
104
|
|
|
47
105
|
Print:
|
|
@@ -49,6 +107,7 @@ Print:
|
|
|
49
107
|
- **Docs updated** (list of files touched)
|
|
50
108
|
- **Verification warnings** (if any)
|
|
51
109
|
- **Tomorrow's top priorities** (carry-forwards + known agenda items)
|
|
110
|
+
- **Task hygiene** (if Step 4.5 changed anything)
|
|
52
111
|
|
|
53
112
|
## Step 6: Commit
|
|
54
113
|
|
package/template/CLAUDE.md
CHANGED
|
@@ -1,144 +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
|
|
5
|
+
Two views of the same project, and Claude operates across both.
|
|
8
6
|
|
|
9
|
-
**
|
|
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.
|
|
10
8
|
|
|
11
|
-
|
|
12
|
-
- **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. The user checks boxes in Obsidian; `tools/tasks/flush-today.js` reconciles those edits back into `tasks.yml`. The user's other primary surface is chat — when they want deep context, they ask, and you traverse the cascade on their behalf.
|
|
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.
|
|
13
10
|
|
|
14
|
-
**
|
|
15
|
-
- Never grow the battle plan's TL;DR into a wall of prose. Keep header blocks terse; append Daily Log entries chronologically.
|
|
16
|
-
- When the user drops new tasks, add them via `node tools/tasks/add.js "..." [--due YYYY-MM-DD] [--tag X] [--priority 1|2|3]`. Don't bury tasks in battle plan prose.
|
|
17
|
-
- After any task mutation (add, complete, snooze), run `node tools/tasks/render-today.js` so `docs/today.md` stays fresh.
|
|
18
|
-
- `verify-cascade.sh` Check 6 confirms `today.md` is not stale relative to `tasks.yml`.
|
|
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.
|
|
19
12
|
|
|
20
13
|
---
|
|
21
14
|
|
|
22
|
-
## The Cascade
|
|
15
|
+
## The Cascade — the core protocol
|
|
23
16
|
|
|
24
|
-
**Trigger:**
|
|
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)
|
|
25
25
|
|
|
26
|
-
When triggered, update in this exact order
|
|
26
|
+
When triggered, update top-down in this exact order. Each step depends on the one above it. Never skip.
|
|
27
27
|
|
|
28
|
-
|
|
29
|
-
|
|
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
|
+
```
|
|
30
44
|
|
|
31
|
-
|
|
32
|
-
- Update the **TL;DR** with current status
|
|
33
|
-
- Update the **Key Metrics** table (numbers reference metrics.yml)
|
|
34
|
-
- Update **Today's Priorities** if relevant
|
|
35
|
-
- Append to **Daily Log** for today
|
|
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).
|
|
36
46
|
|
|
37
|
-
|
|
38
|
-
|
|
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
|
|
39
53
|
|
|
40
|
-
|
|
41
|
-
|-----------|------------|
|
|
42
|
-
| Conversation, call, or meeting | `docs/external-insights.md` — append as new dated session |
|
|
43
|
-
| Evidence for/against a hypothesis | The relevant domain doc — amend the claim with an `[UPDATE]` block |
|
|
44
|
-
| Outreach sent/received | The relevant market or sales doc — update tracking tables |
|
|
45
|
-
| Competitor intel | The relevant strategy or market doc |
|
|
46
|
-
| New foundational knowledge | The relevant research or domain doc |
|
|
54
|
+
Never put state in markdown tables that lives somewhere structured. Never create a parallel store.
|
|
47
55
|
|
|
48
|
-
|
|
56
|
+
---
|
|
49
57
|
|
|
50
|
-
|
|
51
|
-
Run `tools/touch-date.sh` on every file you modified in this session:
|
|
58
|
+
## Behavioral rules — when X happens, do Y
|
|
52
59
|
|
|
53
|
-
|
|
54
|
-
tools/touch-date.sh docs/battle-plan.md docs/validation/hypotheses.md [etc.]
|
|
55
|
-
```
|
|
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`.
|
|
56
61
|
|
|
57
|
-
|
|
58
|
-
Run `tools/verify-cascade.sh` and fix any issues it reports:
|
|
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.
|
|
59
63
|
|
|
60
|
-
|
|
61
|
-
tools/verify-cascade.sh
|
|
62
|
-
```
|
|
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.
|
|
63
65
|
|
|
64
|
-
|
|
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`
|
|
69
|
+
|
|
70
|
+
Numbers native to a doc (where they originate) have no annotation. Verified by `tools/check-metrics.sh`.
|
|
65
71
|
|
|
66
|
-
|
|
72
|
+
**When stating a claim:** mark its confidence — `Unvalidated` / `Soft signal` / `Practitioner-validated` / `Data-validated`. Include the source.
|
|
67
73
|
|
|
68
|
-
|
|
69
|
-
Numbers defined in `metrics.yml`. Reference as: `[**N**](metrics.yml#field_name)`
|
|
74
|
+
**When `verify-cascade.sh` reports an issue:** fix it before ending the turn. Don't ship a known-stale state.
|
|
70
75
|
|
|
71
|
-
|
|
76
|
+
### Outreach add-on (Profile B only — when `outreach/leads.csv` exists)
|
|
72
77
|
|
|
73
|
-
|
|
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.
|
|
74
79
|
|
|
75
|
-
|
|
76
|
-
Less common numbers from another doc. Reference as: `[**N**](source-doc.md#section-slug)`
|
|
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.
|
|
77
81
|
|
|
78
|
-
|
|
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.
|
|
79
83
|
|
|
80
|
-
**
|
|
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.
|
|
81
85
|
|
|
82
86
|
---
|
|
83
87
|
|
|
84
|
-
##
|
|
88
|
+
## Schemas & format
|
|
85
89
|
|
|
86
|
-
|
|
90
|
+
### Document frontmatter (every doc in `docs/`)
|
|
87
91
|
|
|
88
92
|
```markdown
|
|
89
93
|
# Document Title
|
|
90
94
|
|
|
91
|
-
**Last Updated:**
|
|
95
|
+
**Last Updated:** YYYY-MM-DD
|
|
92
96
|
**Status:** Active | Draft | Archived
|
|
93
97
|
**Role:** source-of-truth | cascade-target
|
|
94
98
|
**Compression:** chronological | amended | none
|
|
95
99
|
|
|
96
|
-
**TL;DR:** One paragraph
|
|
97
|
-
|
|
98
|
-
---
|
|
100
|
+
**TL;DR:** One paragraph with key numbers and source references.
|
|
99
101
|
```
|
|
100
102
|
|
|
101
|
-
-
|
|
102
|
-
-
|
|
103
|
-
-
|
|
104
|
-
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
-
|
|
131
|
-
-
|
|
132
|
-
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
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.
|
|
107
|
+
|
|
108
|
+
### Compression modes (drives `/distill`)
|
|
109
|
+
|
|
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. |
|
|
115
|
+
|
|
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.
|
|
117
|
+
|
|
118
|
+
### `tasks.yml` — task lanes
|
|
119
|
+
|
|
120
|
+
Every task has a `lane` (groups by *primary action*, not topic). Default vocabulary (customize in `tools/tasks/lib/tasks.js`):
|
|
121
|
+
|
|
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) |
|
|
130
|
+
|
|
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
|
+
```
|
|
138
165
|
|
|
139
|
-
|
|
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.
|
|
140
167
|
|
|
141
|
-
|
|
168
|
+
### Vault rules
|
|
142
169
|
|
|
143
170
|
1. **Update, don't duplicate.** Amend with `> **[UPDATE YYYY-MM-DD · Source: ...]**`
|
|
144
171
|
2. **Cross-link everything.** Claims reference their source doc.
|
|
@@ -146,95 +173,33 @@ When in doubt about which mode a new doc should use: chronological logs choose `
|
|
|
146
173
|
4. **Source everything.** Who said it, when, confidence level.
|
|
147
174
|
5. **Minimize file count.** Append, don't create new files.
|
|
148
175
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
## The `/wrap-up` Protocol
|
|
152
|
-
|
|
153
|
-
When the user says `/wrap-up`, run this end-of-day sequence:
|
|
154
|
-
|
|
155
|
-
**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
|
|
156
177
|
|
|
157
|
-
|
|
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`).
|
|
158
179
|
|
|
159
|
-
|
|
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`.
|
|
160
181
|
|
|
161
|
-
|
|
182
|
+
Status flow: `new → dm_sent → replied → call_booked → call_done → verbal → loi → paying`. Branches: `dead`, `withdrawn`.
|
|
162
183
|
|
|
163
|
-
|
|
164
|
-
- Metrics changed today (before → after)
|
|
165
|
-
- Docs updated
|
|
166
|
-
- Verification warnings (if any)
|
|
167
|
-
- Tomorrow's top priorities
|
|
168
|
-
|
|
169
|
-
**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.
|
|
170
185
|
|
|
171
186
|
---
|
|
172
187
|
|
|
173
|
-
##
|
|
174
|
-
|
|
175
|
-
**Trigger:** If `outreach/leads.csv` exists in the project, the outreach system is active.
|
|
176
|
-
|
|
177
|
-
### Overview
|
|
178
|
-
|
|
179
|
-
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.
|
|
180
|
-
|
|
181
|
-
### First-Time Setup
|
|
182
|
-
|
|
183
|
-
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.
|
|
184
|
-
|
|
185
|
-
### Daily Workflow Integration
|
|
186
|
-
|
|
187
|
-
The outreach system plugs into the cascade protocol:
|
|
188
|
-
|
|
189
|
-
1. User runs `node tools/outreach/daily-targets.js` → generates blitz checklist
|
|
190
|
-
2. User sends messages, ticks checkboxes
|
|
191
|
-
3. User runs `node tools/outreach/flush-targets.js` → updates leads.csv
|
|
192
|
-
4. `flush-targets.js` calls `sync-metrics.js` → derives metrics.yml from CSV
|
|
193
|
-
5. `sync-metrics.js` calls `update-dashboard.js` → regenerates mermaid dashboard
|
|
194
|
-
6. The cascade protocol takes over: metrics.yml → battle-plan.md → domain docs
|
|
195
|
-
|
|
196
|
-
### Scripts Reference
|
|
197
|
-
|
|
198
|
-
| Script | Purpose |
|
|
199
|
-
|--------|---------|
|
|
200
|
-
| `tools/outreach/daily-targets.js [N]` | Generate daily blitz checklist |
|
|
201
|
-
| `tools/outreach/flush-targets.js` | Process checked items from blitz |
|
|
202
|
-
| `tools/outreach/flush-updates.js` | Parse free-form natural language updates |
|
|
203
|
-
| `tools/outreach/flush-accepts.js` | Batch-process connection accepts |
|
|
204
|
-
| `tools/outreach/flush-inbox.js` | Add leads from manual URL list |
|
|
205
|
-
| `tools/outreach/sync-metrics.js` | Derive metrics.yml from leads.csv |
|
|
206
|
-
| `tools/outreach/update-dashboard.js` | Regenerate mermaid conversion dashboard |
|
|
207
|
-
| `tools/outreach/stats.js` | Print pipeline summary |
|
|
208
|
-
| `tools/outreach/lookup.js "Name"` | Fuzzy-search leads |
|
|
209
|
-
|
|
210
|
-
### Metrics Derivation
|
|
211
|
-
|
|
212
|
-
These metrics in `metrics.yml` are **derived** from leads.csv (never hand-edit):
|
|
213
|
-
|
|
214
|
-
- `outreach_sent` = leads with status past `new` or `contacted_at` set
|
|
215
|
-
- `responses` = `replied_at` set or status past `replied`
|
|
216
|
-
- `invitations_accepted` = leads tagged `accepted`
|
|
217
|
-
- `discovery_calls` = `call_at` in the past or status `call_done`
|
|
218
|
-
- `calls_booked` = status `call_booked` (snapshot)
|
|
219
|
-
- `verbal_commitments` = status `verbal`, `loi`, or `paying`
|
|
220
|
-
|
|
221
|
-
### Template System
|
|
222
|
-
|
|
223
|
-
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.
|
|
224
|
-
|
|
225
|
-
### Mermaid Dashboard
|
|
188
|
+
## Pointers
|
|
226
189
|
|
|
227
|
-
|
|
228
|
-
-
|
|
229
|
-
-
|
|
230
|
-
-
|
|
231
|
-
-
|
|
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
|
|
232
196
|
|
|
233
|
-
|
|
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`.
|
|
234
198
|
|
|
235
|
-
|
|
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
|
|
236
204
|
|
|
237
|
-
-
|
|
238
|
-
- **Different time horizon:** The system tracks weekly breakdowns — adjust `daily-targets.js` count parameter
|
|
239
|
-
- **Different channels:** The `channel` column supports any value (connection, inmail, email, etc.)
|
|
240
|
-
- **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.
|