@open-product-primer/cli 0.9.0 → 0.11.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/dist/commands/init.js +6 -0
- package/dist/lib/install-agent.js +39 -12
- package/package.json +1 -1
package/dist/commands/init.js
CHANGED
|
@@ -128,5 +128,11 @@ function initCommand() {
|
|
|
128
128
|
console.log('\n' + chalk_1.default.green('✓') + ` Agent skills installed: ${selectedAgents.join(', ')}`);
|
|
129
129
|
}
|
|
130
130
|
console.log('\nRun ' + chalk_1.default.cyan('oprim doctor') + ' to verify your setup.');
|
|
131
|
+
console.log('\n' +
|
|
132
|
+
chalk_1.default.bold('Next:') +
|
|
133
|
+
' capture your first product decision. A bet is a time-bound commitment — what you\'re building, why now, and what would make you stop.' +
|
|
134
|
+
'\nOpen your AI agent and run ' +
|
|
135
|
+
chalk_1.default.cyan('/oprim:bet') +
|
|
136
|
+
' to create one.');
|
|
131
137
|
});
|
|
132
138
|
}
|
|
@@ -328,6 +328,8 @@ description: Create a new Product Decision Record in oprim/decisions/ with auto-
|
|
|
328
328
|
|
|
329
329
|
Create a new Product Decision Record (PDR) in \`oprim/decisions/\`.
|
|
330
330
|
|
|
331
|
+
**Interactive prompts:** Use the **AskUserQuestion tool** for every question in this skill — do not write questions as plain text.
|
|
332
|
+
|
|
331
333
|
## Steps
|
|
332
334
|
|
|
333
335
|
### 1. Get the decision title
|
|
@@ -388,6 +390,12 @@ description: Create a new bet directory and bet-decision artifact in oprim/bets/
|
|
|
388
390
|
|
|
389
391
|
Create a new bet in \`oprim/bets/\` and register it on the sequencing board.
|
|
390
392
|
|
|
393
|
+
**Interactive prompts:** Use the **AskUserQuestion tool** for every question in this skill — do not write questions as plain text.
|
|
394
|
+
|
|
395
|
+
## What you're creating
|
|
396
|
+
|
|
397
|
+
A bet is a product decision you're committing to explore: a problem worth solving, a hypothesis worth testing, or a direction worth taking. You'll name it, explain why now, and set a kill criterion so you know when to stop.
|
|
398
|
+
|
|
391
399
|
## Steps
|
|
392
400
|
|
|
393
401
|
### 1. Get the bet title
|
|
@@ -407,7 +415,10 @@ After receiving the title, validate: if fewer than 4 words OR fewer than 25 char
|
|
|
407
415
|
- If "y": proceed with the original title
|
|
408
416
|
|
|
409
417
|
### 2. Assign the next BET ID
|
|
410
|
-
Scan \`oprim/bets/\` for directories
|
|
418
|
+
Scan both \`oprim/bets/\` and \`oprim/bets/archived/\` for directories whose names match \`BET-(\\d+)(-[^/]*)?\` (handles both \`BET-NNN/\` and \`BET-NNN-<slug>/\`). Extract the numeric part from each match. Assign max+1, zero-padded to 3 digits. Default \`001\` if none found in either location.
|
|
419
|
+
|
|
420
|
+
### 2b. Derive the slug
|
|
421
|
+
From the bet title: lowercase all characters, replace any character that is not a letter or digit with a hyphen, collapse consecutive hyphens to one, strip leading/trailing hyphens, truncate to 40 characters at the last hyphen boundary. This becomes \`<slug>\`. Example: "Add title slugs to bet directories for scannability" → \`add-title-slugs-to-bet-dirs-for\`.
|
|
411
422
|
|
|
412
423
|
### 3. Check sequence.yaml exists
|
|
413
424
|
If \`oprim/sequence.yaml\` not found: report and stop — advise \`oprim init\`.
|
|
@@ -415,7 +426,7 @@ If \`oprim/sequence.yaml\` not found: report and stop — advise \`oprim init\`.
|
|
|
415
426
|
### 4. Gather content
|
|
416
427
|
Ask: Decision (Build now / Defer / Kill, default Build now), Owner, Review date (YYYY-MM-DD), Why now, Alternatives considered, Expected outcomes (metric: baseline → target in timeframe), Kill criteria / rollback trigger, PDR links (optional).
|
|
417
428
|
|
|
418
|
-
### 5. Write oprim/bets/BET-NNN
|
|
429
|
+
### 5. Write oprim/bets/BET-NNN-<slug>/bet-decision.md
|
|
419
430
|
\`\`\`
|
|
420
431
|
# Decision: BET-NNN <title>
|
|
421
432
|
<!-- Naming tip: verb + object [for context] — e.g. "Improve bet naming for scannability" not "Naming" -->
|
|
@@ -455,7 +466,7 @@ Read → parse YAML → append → write back (2-space indentation):
|
|
|
455
466
|
|
|
456
467
|
### 7. Prompt for optional discovery scaffolding
|
|
457
468
|
Ask: "Do you want to scaffold a discovery.md now? (y/N)"
|
|
458
|
-
- If "y": write \`oprim/bets/BET-NNN
|
|
469
|
+
- If "y": write \`oprim/bets/BET-NNN-<slug>/discovery.md\` from the discovery template (same structure as \`oprim/templates/discovery.md\`).
|
|
459
470
|
- If "n" or Enter: skip silently.
|
|
460
471
|
|
|
461
472
|
### 8. Report what was created
|
|
@@ -469,6 +480,8 @@ description: Create or append to a criteria.yaml contract for a bet, with struct
|
|
|
469
480
|
|
|
470
481
|
Create or append to \`oprim/bets/BET-NNN/criteria.yaml\`.
|
|
471
482
|
|
|
483
|
+
**Interactive prompts:** Use the **AskUserQuestion tool** for every question in this skill — do not write questions as plain text.
|
|
484
|
+
|
|
472
485
|
## Steps
|
|
473
486
|
|
|
474
487
|
### 1. Identify the bet
|
|
@@ -517,11 +530,13 @@ If not: create with \`metrics:\` list.
|
|
|
517
530
|
function archiveSkill() {
|
|
518
531
|
return `---
|
|
519
532
|
name: oprim-archive
|
|
520
|
-
description: Archive a completed bet — moves it to oprim/bets/archived/
|
|
533
|
+
description: Archive a completed bet — moves it to oprim/bets/archived/ and removes its sequence.yaml entry
|
|
521
534
|
---
|
|
522
535
|
|
|
523
536
|
Archive a completed bet by moving it to \`oprim/bets/archived/\` and removing it from \`sequence.yaml\`.
|
|
524
537
|
|
|
538
|
+
**Interactive prompts:** Use the **AskUserQuestion tool** for every question in this skill — do not write questions as plain text.
|
|
539
|
+
|
|
525
540
|
## Steps
|
|
526
541
|
|
|
527
542
|
### 1. Get the bet ID
|
|
@@ -532,11 +547,19 @@ If not provided, ask: "Which bet ID would you like to archive? (e.g., BET-005)"
|
|
|
532
547
|
|
|
533
548
|
Normalize the input: accept \`bet-005\`, \`005\`, \`5\`, or \`BET-005\` — always treat as \`BET-NNN\` zero-padded to 3 digits.
|
|
534
549
|
|
|
535
|
-
### 2.
|
|
550
|
+
### 2. Resolve the bet directory
|
|
551
|
+
|
|
552
|
+
Look for the bet directory in \`oprim/bets/\` using two patterns:
|
|
553
|
+
1. Exact match: \`oprim/bets/BET-NNN/\` (legacy non-slug format)
|
|
554
|
+
2. Slug variant: any directory starting with \`BET-NNN-\` (e.g., \`BET-NNN-<slug>/\`)
|
|
555
|
+
|
|
556
|
+
Use whichever pattern matches. Call this the **resolved directory name**.
|
|
536
557
|
|
|
537
|
-
|
|
558
|
+
If multiple directories match (e.g., both \`BET-NNN/\` and \`BET-NNN-slug/\` exist):
|
|
559
|
+
- Report: "Ambiguous: found multiple directories for BET-NNN: [list them]. Please archive manually."
|
|
560
|
+
- Stop.
|
|
538
561
|
|
|
539
|
-
If
|
|
562
|
+
If neither pattern matches:
|
|
540
563
|
- Report: "Bet BET-NNN was not found in oprim/bets/. Nothing was changed."
|
|
541
564
|
- Stop.
|
|
542
565
|
|
|
@@ -566,9 +589,9 @@ Create the archive subfolder if it doesn't exist:
|
|
|
566
589
|
mkdir -p oprim/bets/archived
|
|
567
590
|
\`\`\`
|
|
568
591
|
|
|
569
|
-
Move the directory:
|
|
592
|
+
Move the resolved directory:
|
|
570
593
|
\`\`\`bash
|
|
571
|
-
mv oprim/bets
|
|
594
|
+
mv oprim/bets/<resolved-dir> oprim/bets/archived/<resolved-dir>
|
|
572
595
|
\`\`\`
|
|
573
596
|
|
|
574
597
|
### 5. Remove the bet entry from sequence.yaml
|
|
@@ -581,7 +604,7 @@ Read \`oprim/sequence.yaml\`, parse it, and remove the entry with \`id: BET-NNN\
|
|
|
581
604
|
## Bet Archived
|
|
582
605
|
|
|
583
606
|
**Bet:** BET-NNN
|
|
584
|
-
**Archived to:** oprim/bets/archived
|
|
607
|
+
**Archived to:** oprim/bets/archived/<resolved-dir>/
|
|
585
608
|
**Removed from sequence.yaml:** ✓
|
|
586
609
|
|
|
587
610
|
The bet is preserved in full at the archive location.
|
|
@@ -626,6 +649,8 @@ description: Validate and update the primer sequencing board — triage mode com
|
|
|
626
649
|
|
|
627
650
|
Manage the primer sequencing board in \`oprim/sequence.yaml\`.
|
|
628
651
|
|
|
652
|
+
**Interactive prompts:** Use the **AskUserQuestion tool** for every question in this skill — do not write questions as plain text.
|
|
653
|
+
|
|
629
654
|
## Entry modes
|
|
630
655
|
|
|
631
656
|
**Triage mode** — no intention provided: reads board state, computes health, surfaces specific actionable suggestions.
|
|
@@ -718,6 +743,8 @@ description: Create a KPI review artifact for a completed bet, pre-filled from c
|
|
|
718
743
|
|
|
719
744
|
Create a KPI review in \`oprim/reviews/\`.
|
|
720
745
|
|
|
746
|
+
**Interactive prompts:** Use the **AskUserQuestion tool** for every question in this skill — do not write questions as plain text.
|
|
747
|
+
|
|
721
748
|
## Steps
|
|
722
749
|
|
|
723
750
|
### 1. Identify the bet
|
|
@@ -777,7 +804,7 @@ function pdrInlineContent() {
|
|
|
777
804
|
return `Create a new PDR in \`oprim/decisions/\`. Scan for \`PDR-(\\d+)-\` to assign next ID (zero-padded, default 001). Gather: title, context, decision, alternatives, consequences, evidence, related bets/specs. Ask if superseding an existing PDR. Write \`oprim/decisions/PDR-NNN-<slug>.md\`. If superseding: update old PDR Status to "Superseded by PDR-NNN". Report what was created.`;
|
|
778
805
|
}
|
|
779
806
|
function betInlineContent() {
|
|
780
|
-
return `Create a new bet in \`oprim/bets/\`.
|
|
807
|
+
return `Create a new bet in \`oprim/bets/\`. First explain: "A bet is a product decision you're committing to explore — a problem worth solving, a hypothesis worth testing, or a direction worth taking. You'll name it, explain why now, and set a kill criterion." Then show: "Naming tip: verb + object [for context] — Good: 'Improve bet naming for scannability' / Bad: 'Naming'". Scan \`BET-(\\d+)\` dirs for next ID (zero-padded, default 001). Check \`oprim/sequence.yaml\` exists (stop if not — advise oprim init). After receiving the title, validate: if fewer than 4 words OR fewer than 25 characters, warn "this title may be too vague", suggest a reformulation, and ask "Proceed anyway? (y/N)" — if "n", prompt for a revised title. Gather: decision (default Build now), owner, review date, why-now, alternatives, expected outcomes, kill criteria, PDR links. Write \`oprim/bets/BET-NNN/bet-decision.md\` with an inline naming tip comment in the header. Append entry to sequence.yaml backlog: \`{id, title, blocked_by: [], unlocks: [], requires_pdrs: []}\`. Then ask: "Do you want to scaffold a discovery.md now? (y/N)" — if "y", write \`oprim/bets/BET-NNN/discovery.md\` from the discovery template (sections: Problem Framing, User Research Signals, Competitive Context, Open Questions); if "n" or Enter, skip silently. Report what was created.`;
|
|
781
808
|
}
|
|
782
809
|
function criteriaInlineContent() {
|
|
783
810
|
return `Add metrics to \`oprim/bets/BET-NNN/criteria.yaml\`. Verify bet dir exists. Gather: metric ID, name, baseline, target, timeframe, launch date, segment. Ask source type (amplitude or bigquery). Amplitude: event, aggregation, denominator_event. BigQuery: table, metric_column, filter, aggregation, denominator_query. If file exists: append to metrics list (never overwrite). If not: create. Ask if adding more metrics. Report what was created.`;
|
|
@@ -826,7 +853,6 @@ nudge_flag=".claude/hooks/.sequence-nudge"
|
|
|
826
853
|
# --- Archive co-archival block ---
|
|
827
854
|
if [ -f "$archive_flag" ]; then
|
|
828
855
|
change=$(tr -d '[:space:]' < "$archive_flag")
|
|
829
|
-
rm -f "$archive_flag"
|
|
830
856
|
|
|
831
857
|
if [ -z "$change" ]; then
|
|
832
858
|
latest=$(ls openspec/changes/archive/ 2>/dev/null | sort -r | head -1)
|
|
@@ -836,6 +862,7 @@ if [ -f "$archive_flag" ]; then
|
|
|
836
862
|
if [ -n "$change" ]; then
|
|
837
863
|
archive_dir=$(ls openspec/changes/archive/ 2>/dev/null | grep -F "$change" | sort -r | head -1)
|
|
838
864
|
if [ -n "$archive_dir" ]; then
|
|
865
|
+
rm -f "$archive_flag"
|
|
839
866
|
proposal="openspec/changes/archive/$archive_dir/proposal.md"
|
|
840
867
|
if [ -f "$proposal" ]; then
|
|
841
868
|
bet_id=$(grep -oE 'BET-[0-9]+' "$proposal" | head -1)
|