create-battle-plan 1.4.4 → 1.5.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/bin/cli.js CHANGED
@@ -71,14 +71,6 @@ function ask(question) {
71
71
  });
72
72
  }
73
73
 
74
- async function askRequired(question, errorMsg) {
75
- while (true) {
76
- const answer = await ask(question);
77
- if (answer) return answer;
78
- console.log(`${YELLOW} ${errorMsg}${RESET}`);
79
- }
80
- }
81
-
82
74
  // ── Interactive folder picker (raw mode) ─────────────────
83
75
 
84
76
  function getDirs(dir) {
@@ -317,66 +309,155 @@ async function main() {
317
309
 
318
310
  initReadline();
319
311
 
320
- // Question 1: Project description (one sentence used for context, not the folder name)
321
- const projectName = await askRequired(
322
- `${DIM}[1/7]${RESET} ${BOLD}What's your project in one sentence?${RESET}\n> `,
323
- 'A one-sentence description is required — even rough is fine. Try again:'
324
- );
312
+ // Type `:back` (or `:b`) at any prompt to revise the previous answer.
313
+ console.log(`${DIM} tip: type ${BOLD}:back${RESET}${DIM} at any prompt to revise the previous answer${RESET}`);
325
314
  console.log('');
326
315
 
327
- // Question 2: Short name (the actual folder slug). Default = cwd basename when sensible.
328
- const cwdBasename = path.basename(process.cwd());
329
- const cwdSlug = slugify(cwdBasename);
330
- const cwdIsEmpty = (() => {
331
- try { return fs.readdirSync(process.cwd()).length === 0; } catch { return false; }
332
- })();
333
- const sentenceSlug = slugify(projectName);
334
- const truncatedSentenceSlug = sentenceSlug.split('-').slice(0, 3).join('-');
335
- const genericNames = new Set(['projects', 'code', 'src', 'work', 'dev', 'repos', 'workspace', 'documents', 'desktop']);
336
- const defaultShortName = (cwdIsEmpty && cwdSlug && !genericNames.has(cwdSlug))
337
- ? cwdSlug
338
- : (truncatedSentenceSlug || 'my-battle-plan');
339
- const shortNameRaw = await ask(
340
- `${DIM}[2/7]${RESET} ${BOLD}Short name for the folder?${RESET} ${DIM}(default: ${defaultShortName})${RESET}\n> `
341
- );
342
- const shortName = slugify(shortNameRaw) || defaultShortName;
343
- console.log('');
316
+ const isBack = (s) => {
317
+ const t = s.trim().toLowerCase();
318
+ return t === ':back' || t === ':b';
319
+ };
320
+
321
+ // Each step reads `a` (answers so far) and writes its key. Returns {back:true}
322
+ // to step backwards, or {value} to advance. When `a[key]` already has a value
323
+ // (revisit), prompts show "press enter to keep" and accept empty input.
324
+ const a = {};
325
+
326
+ async function stepProject() {
327
+ const prior = a.projectName;
328
+ const hint = prior ? ` ${DIM}(currently: "${prior.length > 40 ? prior.slice(0, 40) + '…' : prior}" — enter to keep)${RESET}` : '';
329
+ while (true) {
330
+ const raw = await ask(`${DIM}[1/7]${RESET} ${BOLD}What's your project in one sentence?${RESET}${hint}\n> `);
331
+ if (isBack(raw)) return { back: true };
332
+ const v = raw.trim() || prior;
333
+ if (!v) {
334
+ console.log(`${YELLOW} A one-sentence description is required — even rough is fine. Try again:${RESET}`);
335
+ continue;
336
+ }
337
+ return { value: v };
338
+ }
339
+ }
344
340
 
345
- // Question 3: Time horizon
346
- const horizon = await ask(
347
- `${DIM}[3/7]${RESET} ${BOLD}What's your time horizon?${RESET} ${DIM}(e.g., "3 weeks to demo day", "6 months to launch", "ongoing")${RESET}\n> `
348
- );
349
- console.log('');
341
+ async function stepShortName() {
342
+ const cwdBasename = path.basename(process.cwd());
343
+ const cwdSlug = slugify(cwdBasename);
344
+ const cwdIsEmpty = (() => {
345
+ try { return fs.readdirSync(process.cwd()).length === 0; } catch { return false; }
346
+ })();
347
+ const sentenceSlug = slugify(a.projectName);
348
+ const truncatedSentenceSlug = sentenceSlug.split('-').slice(0, 3).join('-');
349
+ const genericNames = new Set(['projects', 'code', 'src', 'work', 'dev', 'repos', 'workspace', 'documents', 'desktop']);
350
+ const defaultShortName = (cwdIsEmpty && cwdSlug && !genericNames.has(cwdSlug))
351
+ ? cwdSlug
352
+ : (truncatedSentenceSlug || 'my-battle-plan');
353
+ const prior = a.shortName;
354
+ const hint = prior
355
+ ? `${DIM}(currently: "${prior}" — enter to keep)${RESET}`
356
+ : `${DIM}(default: ${defaultShortName})${RESET}`;
357
+ const raw = await ask(`${DIM}[2/7]${RESET} ${BOLD}Short name for the folder?${RESET} ${hint}\n> `);
358
+ if (isBack(raw)) return { back: true };
359
+ const trimmed = raw.trim();
360
+ const value = trimmed
361
+ ? (slugify(trimmed) || defaultShortName)
362
+ : (prior || defaultShortName);
363
+ return { value };
364
+ }
350
365
 
351
- // Question 4: Metrics (optional — leave blank for journal-style projects)
352
- const metricsRaw = await ask(
353
- `${DIM}[4/7]${RESET} ${BOLD}Any metrics to track?${RESET} ${DIM}(comma-separated, e.g., "outreach sent, calls booked, LOIs signed" — or press enter to skip)${RESET}\n> `
354
- );
355
- const metrics = metricsRaw
356
- ? metricsRaw.split(',').map((m) => m.trim()).filter(Boolean)
357
- : [];
358
- console.log('');
366
+ async function stepHorizon() {
367
+ const prior = a.horizon;
368
+ const hint = prior
369
+ ? `${DIM}(currently: "${prior}" — enter to keep)${RESET}`
370
+ : `${DIM}(e.g., "3 weeks to demo day", "6 months to launch", "ongoing")${RESET}`;
371
+ const raw = await ask(`${DIM}[3/7]${RESET} ${BOLD}What's your time horizon?${RESET} ${hint}\n> `);
372
+ if (isBack(raw)) return { back: true };
373
+ const trimmed = raw.trim();
374
+ return { value: trimmed || prior || '' };
375
+ }
359
376
 
360
- // Question 5: Domains
361
- const suggested = suggestDomains(projectName);
362
- const domainsRaw = await askRequired(
363
- `${DIM}[5/7]${RESET} ${BOLD}What domains does your work cover?${RESET} ${DIM}(comma-separated)\nSuggested based on your project: ${suggested}${RESET}\n> `,
364
- `At least one domain is required try the suggestions (${suggested}) or any topic area. Try again:`
365
- );
366
- const domains = domainsRaw.split(',').map((d) => d.trim().toLowerCase()).filter(Boolean);
367
- console.log('');
377
+ async function stepMetrics() {
378
+ const prior = a.metrics;
379
+ const priorDisplay = prior && prior.length ? prior.join(', ') : '';
380
+ const hint = priorDisplay
381
+ ? `${DIM}(currently: "${priorDisplay}" enter to keep, type "none" to clear)${RESET}`
382
+ : `${DIM}(comma-separated, e.g., "outreach sent, calls booked, LOIs signed" — or press enter to skip)${RESET}`;
383
+ const raw = await ask(`${DIM}[4/7]${RESET} ${BOLD}Any metrics to track?${RESET} ${hint}\n> `);
384
+ if (isBack(raw)) return { back: true };
385
+ const trimmed = raw.trim();
386
+ if (trimmed.toLowerCase() === 'none') return { value: [] };
387
+ if (!trimmed) return { value: prior || [] };
388
+ return { value: trimmed.split(',').map((m) => m.trim()).filter(Boolean) };
389
+ }
368
390
 
369
- // Question 6: People
370
- const peopleRaw = await ask(
371
- `${DIM}[6/7]${RESET} ${BOLD}Who are the key people you'll be working with?${RESET} ${DIM}(format: "Name:Role, Name:Role" — or press enter to skip)${RESET}\n> `
372
- );
373
- const people = peopleRaw
374
- ? peopleRaw.split(',').map((p) => {
391
+ async function stepDomains() {
392
+ const prior = a.domains;
393
+ const suggested = suggestDomains(a.projectName);
394
+ const priorDisplay = prior && prior.length ? prior.join(', ') : '';
395
+ const hint = priorDisplay
396
+ ? `${DIM}(currently: "${priorDisplay}" — enter to keep)${RESET}`
397
+ : `${DIM}(comma-separated)\nSuggested based on your project: ${suggested}${RESET}`;
398
+ while (true) {
399
+ const raw = await ask(`${DIM}[5/7]${RESET} ${BOLD}What domains does your work cover?${RESET} ${hint}\n> `);
400
+ if (isBack(raw)) return { back: true };
401
+ const trimmed = raw.trim();
402
+ if (!trimmed) {
403
+ if (prior && prior.length) return { value: prior };
404
+ console.log(`${YELLOW} At least one domain is required — try the suggestions (${suggested}) or any topic area. Try again:${RESET}`);
405
+ continue;
406
+ }
407
+ return { value: trimmed.split(',').map((d) => d.trim().toLowerCase()).filter(Boolean) };
408
+ }
409
+ }
410
+
411
+ async function stepPeople() {
412
+ const prior = a.people;
413
+ const priorDisplay = prior && prior.length ? prior.map((p) => `${p.name}:${p.role}`).join(', ') : '';
414
+ const hint = priorDisplay
415
+ ? `${DIM}(currently: "${priorDisplay}" — enter to keep, type "none" to clear)${RESET}`
416
+ : `${DIM}(format: "Name:Role, Name:Role" — or press enter to skip)${RESET}`;
417
+ const raw = await ask(`${DIM}[6/7]${RESET} ${BOLD}Who are the key people you'll be working with?${RESET} ${hint}\n> `);
418
+ if (isBack(raw)) return { back: true };
419
+ const trimmed = raw.trim();
420
+ if (trimmed.toLowerCase() === 'none') return { value: [] };
421
+ if (!trimmed) return { value: prior || [] };
422
+ return {
423
+ value: trimmed.split(',').map((p) => {
375
424
  const [name, role] = p.split(':').map((s) => s.trim());
376
425
  return { name: name || '', role: role || '' };
377
- }).filter((p) => p.name)
378
- : [];
379
- console.log('');
426
+ }).filter((p) => p.name),
427
+ };
428
+ }
429
+
430
+ const steps = [
431
+ { key: 'projectName', run: stepProject },
432
+ { key: 'shortName', run: stepShortName },
433
+ { key: 'horizon', run: stepHorizon },
434
+ { key: 'metrics', run: stepMetrics },
435
+ { key: 'domains', run: stepDomains },
436
+ { key: 'people', run: stepPeople },
437
+ ];
438
+
439
+ let i = 0;
440
+ while (i < steps.length) {
441
+ const r = await steps[i].run();
442
+ if (r.back) {
443
+ if (i === 0) {
444
+ console.log(`${YELLOW} Already at the first question.${RESET}`);
445
+ continue;
446
+ }
447
+ i--;
448
+ continue;
449
+ }
450
+ a[steps[i].key] = r.value;
451
+ console.log('');
452
+ i++;
453
+ }
454
+
455
+ const projectName = a.projectName;
456
+ const shortName = a.shortName;
457
+ const horizon = a.horizon;
458
+ const metrics = a.metrics;
459
+ const domains = a.domains;
460
+ const people = a.people;
380
461
 
381
462
  // Question 7: Interactive folder picker
382
463
  const targetDir = await pickFolder(shortName);
@@ -586,7 +667,7 @@ ${peopleSections}
586
667
  console.log(`${DIM} + docs/battle-plan.md${RESET}`);
587
668
  console.log(`${DIM} + docs/external-insights.md${RESET}`);
588
669
 
589
- // Save onboarding answers for Claude to read on first /good-morning
670
+ // Save onboarding answers for Claude to read on first /welcome
590
671
  fs.writeFileSync(
591
672
  path.join(targetDir, '.battle-plan-onboarding.json'),
592
673
  JSON.stringify(
@@ -649,10 +730,13 @@ ${peopleSections}
649
730
  console.log(`${DIM} │${RESET} ${BOLD}cd ${relPath} && claude${RESET}${DIM}${' '.repeat(Math.max(0, 37 - relPath.length - 12))}│${RESET}`);
650
731
  console.log(`${DIM} └─────────────────────────────────────────┘${RESET}`);
651
732
  console.log('');
652
- console.log(` Once Claude is running, type ${GREEN}${BOLD}/good-morning${RESET}`);
653
- console.log(` to start your first session. Claude will`);
654
- console.log(` introduce itself, explain how everything`);
655
- console.log(` works, and help you set your first targets.`);
733
+ console.log(` Once Claude is running, type ${GREEN}${BOLD}/welcome${RESET}`);
734
+ console.log(` for a guided tour Claude will introduce`);
735
+ console.log(` itself, walk you through how the system works,`);
736
+ console.log(` and tailor things to how you want to use it.`);
737
+ console.log('');
738
+ console.log(` ${DIM}(After that, use ${BOLD}/good-morning${RESET}${DIM} to start each day${RESET}`);
739
+ console.log(` ${DIM}and ${BOLD}/wrap-up${RESET}${DIM} to close it out.)${RESET}`);
656
740
  console.log('');
657
741
  }
658
742
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-battle-plan",
3
- "version": "1.4.4",
3
+ "version": "1.5.0",
4
4
  "description": "Scaffold a Battle Plan project — a markdown-based context system for LLM-powered project management",
5
5
  "bin": {
6
6
  "create-battle-plan": "./bin/cli.js"
@@ -6,63 +6,18 @@ description: Morning standup — status briefing, metrics snapshot, and today's
6
6
 
7
7
  Run these steps in order.
8
8
 
9
- ## Step 0: First-Run Welcome (one time only)
9
+ ## Step 0: First-run gate
10
10
 
11
- Check if `.battle-plan-onboarding.json` exists in the repo root. If it does, this is the user's **FIRST session** after running `npx create-battle-plan`. This is a special moment the user just installed this and wants to understand what they've got. Make them feel like their project is in good hands.
11
+ If `.battle-plan-onboarding.json` exists in the repo root, the user hasn't run `/welcome` yet. Don't run the standuptell them:
12
12
 
13
- **Read `.battle-plan-onboarding.json`** to get their project context. Then write a warm, personal welcome that covers ALL of the following. This should feel like a knowledgeable co-pilot introducing itself, not a product manual.
13
+ > Hey looks like this is a fresh install and you haven't gone through the welcome yet. Run `/welcome` first to get the proper tour, then come back to `/good-morning` tomorrow (or whenever you start your next session).
14
14
 
15
- ### Part 1: Personal welcome (reflect their project back to them)
15
+ Stop here. Don't proceed to Step 1.
16
16
 
17
- Greet them warmly. Show them you already know their project by name, their time horizon, their metrics, their domains, and their people. Reference these specifics naturally don't just list them. The user should feel like they're continuing a conversation, not configuring a tool.
18
-
19
- Example tone: "Welcome to your battle plan for [project]. You've got [horizon] and you're tracking [metrics] — I've got all of that loaded and ready to go."
20
-
21
- ### Part 2: What this is (the big picture)
22
-
23
- Explain what they now have, in plain language:
24
-
25
- - **This is your project's memory.** Every conversation, decision, metric, and insight lives here in markdown files. When you close this chat and come back tomorrow — or next week — I read these files and pick up exactly where we left off. Nothing gets lost between sessions.
26
- - **You don't organize anything.** When you tell me something new — a call you had, research you found, a number that changed, a reply you got — I update the right files in the right order automatically. That's called the cascade.
27
- - **The cascade works like this:** new info flows into `metrics.yml` first (if a number changed), then into your battle plan (the operating doc that tracks where you are), then into the source docs for each domain. At the end, a verification script checks that everything is consistent.
28
- - **Think of it as dumping context.** You can paste a full call transcript, a messy list of notes, a forwarded email, a research summary — anything. You don't need to format it or tell me where it goes. Just dump it in and I'll cascade it to the right places.
29
-
30
- ### Part 3: How to use it day to day
31
-
32
- Explain the rhythm:
33
-
34
- - **Start each session** with `/good-morning` (what you just ran). I'll brief you on where you stand — metrics, priorities, what's stuck, what's next. Think of it as a daily standup with your AI co-pilot.
35
- - **During the day**, just talk to me. Tell me what happened, paste in notes, ask me to update things. Every piece of new info triggers the cascade automatically.
36
- - **End each session** with `/wrap-up`. I'll review the day, show you what changed, sync everything, and offer to commit. This is how you close out clean without forgetting to log something.
37
- - **When docs get long**, run `/distill`. Over time, your daily logs and conversation journals will grow. `/distill` compresses older content into a thorough summary and archives the raw text — nothing is ever deleted, but I can read the docs faster.
38
-
39
- ### Part 4: How metrics work
40
-
41
- - Your key metrics live in `metrics.yml` — it's the single numeric source of truth for the whole project.
42
- - Every number that appears in any doc traces back to that file via source annotations. When a metric changes, the cascade propagates the new value everywhere it's referenced.
43
- - Shell scripts verify the numbers stay in sync. You'll never have a stale "42" in one doc when the real number is "47" in another.
44
- - Right now all your metrics are at zero. One of the first things we'll do is set targets.
45
-
46
- ### Part 5: What to do right now
47
-
48
- Transition into action:
49
-
50
- - "Let's start by getting some real data into the system. Here's what I'd suggest..."
51
- - Prompt them to set targets for their metrics
52
- - Ask if there's any existing context they already have — calls they've had, research they've done, decisions they've already made. Anything they can tell you now will make the battle plan immediately useful.
53
-
54
- ### After the welcome
55
-
56
- Rename `.battle-plan-onboarding.json` to `.battle-plan-onboarding-done.json` so this welcome doesn't repeat.
57
-
58
- Then show a **compact metrics table** (all zeros, no targets yet) and transition into the onboarding questions naturally. Don't run the full standup format (Steps 1-4 below) on the first run — there's nothing to report yet. Instead, go straight to helping them populate the battle plan.
59
-
60
- ---
17
+ If neither `.battle-plan-onboarding.json` nor `.battle-plan-onboarding-done.json` exists, continue normallythe project may have been bootstrapped without the create-battle-plan CLI.
61
18
 
62
19
  ## Step 1: Gather State (parallel reads)
63
20
 
64
- *Skip this on first run (Step 0 handles it). On all subsequent runs, start here.*
65
-
66
21
  Run these in parallel:
67
22
  - `node tools/tasks/render-today.js --quiet` — regenerate `docs/today.md` from `tasks.yml`
68
23
  - Read `metrics.yml` — current numbers
@@ -122,6 +77,4 @@ After the user answers:
122
77
 
123
78
  ## Tone
124
79
 
125
- On first run: warm, confident, thorough. The user should feel like they just hired a great project manager who already read the brief.
126
-
127
- On subsequent runs: direct, no fluff. Think military briefing, not newsletter.
80
+ Direct, no fluff. Think military briefing, not newsletter. The user is starting a work session — they want their position and their next move, not a pep talk. (First-session warmth lives in `/welcome`, not here.)
@@ -0,0 +1,112 @@
1
+ ---
2
+ description: First-session welcome — introduces the system, asks about project archetype, tailors onboarding. Runs ONCE after install. Use /good-morning for daily standups thereafter.
3
+ ---
4
+
5
+ # Welcome
6
+
7
+ Run this ONCE, on the user's very first session after `npx create-battle-plan`.
8
+
9
+ ## Has welcome already run?
10
+
11
+ Check the repo root:
12
+ - If `.battle-plan-onboarding-done.json` exists → welcome already completed. Tell the user: `/welcome` is for first-time setup only. Suggest `/good-morning` (start of day) or `/wrap-up` (end of day) instead. Don't run the rest of this skill.
13
+ - If neither `.battle-plan-onboarding.json` nor `.battle-plan-onboarding-done.json` exists → the project wasn't scaffolded via `create-battle-plan`. Tell the user `/welcome` is meant for first-run after install and there's no onboarding context to load. Offer to walk through the system manually if they want.
14
+ - If `.battle-plan-onboarding.json` exists → continue.
15
+
16
+ Read `.battle-plan-onboarding.json` for project context (name, horizon, metrics, domains, people). Keep these handy — you'll reference them throughout.
17
+
18
+ ---
19
+
20
+ ## Step 1 — Personal welcome (one message)
21
+
22
+ Greet by name. Show you already know their project — reference their horizon, the specific domains they picked, the people they named. Do this naturally, not as a recital. The user should feel like they're continuing a conversation, not booting up a tool.
23
+
24
+ If they declared metrics, mention them. If they didn't (`metrics: []` in the json), don't pretend they did — acknowledge this is a journal-style or open-ended project. Example: "I see you didn't declare specific metrics — that's fine, plenty of projects don't need them upfront. We can stay narrative and add them later if patterns emerge."
25
+
26
+ End this message with: "Before we go anywhere, let me show you around — and then I want to ask you a couple of things about how you want to use this."
27
+
28
+ ---
29
+
30
+ ## Step 2 — Plain-language tour (one message, no jargon dumps)
31
+
32
+ Explain what they actually have. Cover, in this order, in your own words:
33
+
34
+ 1. **It's your project's memory.** Markdown files in `docs/`, plus three structured YAML files (`metrics.yml`, `tasks.yml`, `events.yml`). When the user closes the session and comes back next week, you read these and pick up exactly where you left off. Nothing gets lost.
35
+ 2. **They don't organize anything.** When the user tells you something new — a call they had, an article they read, a number that changed, an idea, a forwarded email — you update the right files in the right order. That's the cascade.
36
+ 3. **The cascade flows top-down.** Raw state (metrics / events / tasks) → `battle-plan.md` (current state) → source docs per domain → verification script. The user never has to know this exists — they just dump stuff in chat.
37
+ 4. **The chat is the UI.** The cascade is your memory, not theirs. `docs/today.md` is the only file they should ever need to open — it's a thin clickable surface they can tick through in Obsidian or any markdown viewer.
38
+ 5. **Compression keeps it readable.** Daily logs and conversation journals grow over time. `/distill` collapses old content into a thorough summary, archives the raw text, nothing is ever deleted.
39
+
40
+ Keep this to ~6–10 sentences total. Don't enumerate every file. Don't show code. The goal is to land the *shape* of the system, not the schema.
41
+
42
+ End with: "Now — quick question so I can tailor this to you."
43
+
44
+ ---
45
+
46
+ ## Step 3 — Detect the archetype (ASK, don't assume)
47
+
48
+ The system was originally built for founders validating an idea (metric-heavy: outreach, calls booked, conversion). But it works just as well for several other shapes. Ask:
49
+
50
+ > "Which of these sounds closest to what you're doing here? You can pick one, or say 'mix' if it's blended.
51
+ >
52
+ > **(a) Founder / operator validating an idea.** Metric-driven. Outreach, calls, replies, conversion. You want to know if this idea is real.
53
+ > **(b) Metric-heavy ops project.** Compliance work, sales pipeline, a specific build. Clear numbers to track, deadlines, deliverables.
54
+ > **(c) Journal / second-brain.** Dream journal, life admin, ongoing context layer. Few or no metrics — just want to dump stuff and have it organized.
55
+ > **(d) Something else.** Tell me about it."
56
+
57
+ Wait for the answer.
58
+
59
+ ### How to tailor based on the archetype
60
+
61
+ | Archetype | Tailoring |
62
+ |---|---|
63
+ | **(a) founder-validation** | Default behavior. Push toward setting outreach/conversion targets. Expect them to track leads (suggest the outreach add-on if they don't have it — see `outreach/README.md`). Daily rhythm: `/good-morning` → work → `/wrap-up`. Weekly: `/weekly-triage`. |
64
+ | **(b) metric-heavy ops** | Same daily rhythm. Help them define the right metrics for their domain (deadlines, deliverables, throughput, error rate, whatever). Suggest setting `events.yml` for any scheduled meetings or deadlines. |
65
+ | **(c) journal / second-brain** | Lower-touch. They probably don't need `/wrap-up` daily — once a week is fine. The cascade still works, but the value is in *querying* the dump later, not in metric drift. Tell them: just talk to you in chat, and you'll keep the docs organized. They can rerun `/distill` when things get long. |
66
+ | **(d) other / mix** | Ask 1–2 follow-up questions to figure out the shape, then map to (a)/(b)/(c) or invent a hybrid. |
67
+
68
+ After they answer, give them a short, archetype-specific reflection: "Got it — so for you, the rhythm is going to look like X. Here's what I'd suggest as a starting point…"
69
+
70
+ ---
71
+
72
+ ## Step 4 — Tour the slash commands (one message)
73
+
74
+ Show the four daily/weekly commands with one-line descriptions, tailored to their archetype:
75
+
76
+ - **`/good-morning`** — start of session. I brief you on where you stand, what's open, what to push on today. Use every day you sit down with this. *(Mention this is the one they'll run tomorrow.)*
77
+ - **`/wrap-up`** — end of session. I reconcile the day, run the cascade, show what changed, offer to commit. *(For journal-style users: "Every few days is fine, doesn't have to be daily.")*
78
+ - **`/weekly-triage`** — weekly sweep of `tasks.yml`. Catches stale tasks, drift, overdue items. *(Skip if they're archetype (c).)*
79
+ - **`/distill`** — when a doc gets long. Compresses old content, archives raw, keeps recent. Run when you notice me being slow to load a file.
80
+
81
+ Don't dump the full skill list. The user can discover the others later.
82
+
83
+ ---
84
+
85
+ ## Step 5 — Seed the system with existing context
86
+
87
+ Ask:
88
+
89
+ > "One last thing before we close this out: is there anything you already know about this project that I should have? Past calls, research you've read, decisions you've made, key contacts, anything. You don't need to structure it — just dump it and I'll cascade it into the right docs."
90
+
91
+ If they share anything, run the full cascade (Steps 0–4 from `CLAUDE.md`). If they say "nothing yet," skip.
92
+
93
+ For archetype (a) or (b): if they declared metrics in onboarding but didn't set targets, prompt them now: "What would success look like for [metric]? Even a rough number is fine." Update `battle-plan.md` with the targets.
94
+
95
+ ---
96
+
97
+ ## Step 6 — Mark welcome complete
98
+
99
+ Rename `.battle-plan-onboarding.json` → `.battle-plan-onboarding-done.json` so this skill doesn't trigger again. Use the `mv` command via Bash, or the `Write` + delete pattern if `mv` isn't permitted.
100
+
101
+ Tell the user:
102
+ - "You're set up. Welcome doesn't run again."
103
+ - "Tomorrow, start with `/good-morning`. End with `/wrap-up` whenever you wind down."
104
+ - "Anything you tell me in between just gets cascaded — no special commands needed."
105
+
106
+ ---
107
+
108
+ ## Tone
109
+
110
+ Warm, thorough, but not preachy. The user just installed something — they're curious and a little uncertain. You're a knowledgeable co-pilot introducing themselves, not a product tour with arrows and tooltips. Default to plain English; reach for terminology (cascade, distill, compression mode) only after you've explained what it means. Never read the user a list of internal filenames unless they ask.
111
+
112
+ It's fine to take 4–6 messages to get through this — don't try to compress it into one wall of text.
@@ -197,7 +197,8 @@ Tags grow forward with `, ` separator. Notes grow forward with `| ` separator
197
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`.
198
198
 
199
199
  **Skills (`.claude/commands/`):**
200
- - `good-morning` — morning standup (metrics + today.md + events context-debt check)
200
+ - `welcome` — first-session tour (runs once, after `npx create-battle-plan`). Introduces the system, detects project archetype, tailors onboarding.
201
+ - `good-morning` — morning standup (metrics + today.md + events context-debt check). Refuses to run until `/welcome` has completed.
201
202
  - `wrap-up` — end-of-day reconciliation + task hygiene + events gate
202
203
  - `weekly-triage` — task-pile sweep
203
204
  - `distill` — compress chronological / amended doc history