miriad-viz 0.2.0 → 0.2.2

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.
@@ -132,7 +132,7 @@ function generateRetroPageData(dateRange, agents, rosterTypes) {
132
132
  const midISO = new Date(Math.round((startMs + endMs) / 2)).toISOString();
133
133
  const totalHours = dateRange?.hours ?? 0;
134
134
  return {
135
- _comment: "Fill in phases, milestones, quotes, and trust arc. See docs/curation-guide.md for details.",
135
+ _comment: "Fill in phases, milestones, quotes, and trust arc.",
136
136
  meta: {
137
137
  title: "Project Title",
138
138
  subtitle: "A brief description of the project",
@@ -241,7 +241,7 @@ function generateRetroPageData(dateRange, agents, rosterTypes) {
241
241
  }
242
242
  function generateRetroPageQuotes() {
243
243
  return {
244
- _comment: 'Additional quotes organized by category. See docs/curation-guide.md. Timestamps can be informal like "Feb 10 21:18". Avoid placing two quotes from the same agent close together \u2014 interleave different agents.',
244
+ _comment: 'Additional quotes organized by category. Timestamps can be informal like "Feb 10 21:18". Avoid placing two quotes from the same agent close together \u2014 interleave different agents.',
245
245
  good: [
246
246
  {
247
247
  text: "Replace with a positive quote",
@@ -422,7 +422,6 @@ Your project spans ${dateRange.hours} hours.`);
422
422
  if (agents.length > 0) {
423
423
  console.log(`Agents: ${agents.join(", ")}`);
424
424
  }
425
- console.log("\nSee: docs/curation-guide.md");
426
425
  progress.steps.curate = { status: "in_progress" };
427
426
  writeProgress(projectDir, progress);
428
427
  console.log("\nEdit the scaffold files, then run 'npx miriad-viz next' to continue.");
package/dist-cli/index.js CHANGED
@@ -9,8 +9,8 @@ import {
9
9
  } from "./chunk-E6W6WNZ6.js";
10
10
 
11
11
  // src/cli/guided/index.ts
12
- import { existsSync as existsSync2, readFileSync, readdirSync } from "fs";
13
- import { resolve as resolve2 } from "path";
12
+ import { existsSync as existsSync3, readFileSync as readFileSync2, readdirSync } from "fs";
13
+ import { resolve as resolve3 } from "path";
14
14
 
15
15
  // src/cli/guided/data-summary.ts
16
16
  function buildDataSummary(data) {
@@ -61,6 +61,30 @@ function buildDataSummary(data) {
61
61
  return lines;
62
62
  }
63
63
 
64
+ // src/cli/guided/docs.ts
65
+ import { existsSync, readFileSync } from "fs";
66
+ import { resolve } from "path";
67
+ import { fileURLToPath } from "url";
68
+ function readBundledDoc(slug) {
69
+ const thisFile = fileURLToPath(import.meta.url);
70
+ const docsDir = findDocsDir(thisFile);
71
+ if (!docsDir) return null;
72
+ const filePath = resolve(docsDir, `${slug}.md`);
73
+ if (!existsSync(filePath)) return null;
74
+ return readFileSync(filePath, "utf-8");
75
+ }
76
+ function findDocsDir(fromFile) {
77
+ let dir = resolve(fromFile, "..");
78
+ for (let i = 0; i < 10; i++) {
79
+ const candidate = resolve(dir, "docs");
80
+ if (existsSync(resolve(dir, "package.json")) && existsSync(candidate)) {
81
+ return candidate;
82
+ }
83
+ dir = resolve(dir, "..");
84
+ }
85
+ return null;
86
+ }
87
+
64
88
  // src/cli/guided/next.ts
65
89
  var AUDIO_DIR_PREFIX = "remotion/public/audio/";
66
90
  function buildCommand(step, progress, flags) {
@@ -116,9 +140,8 @@ function computeNext(progress, existingFiles, logTails, flags = {}, dataSummary,
116
140
  return { action: "all_done", progress, output: output2 };
117
141
  }
118
142
  const config = STEP_CONFIG[step];
119
- const output = [
120
- config.creative ? "\u26D4 FOLLOW THESE INSTRUCTIONS EXACTLY. This is a CREATIVE step \u2014 present results to the human and WAIT for their direction before proceeding." : "\u26D4 FOLLOW THESE INSTRUCTIONS EXACTLY. This is a mechanical step \u2014 run it, report the result, then call `next` again."
121
- ];
143
+ const stepPrefix = step === "extract" ? "\u26D4 FOLLOW THESE INSTRUCTIONS EXACTLY. This step requires human input BEFORE running any commands." : config.creative ? "\u26D4 FOLLOW THESE INSTRUCTIONS EXACTLY. This is a CREATIVE step \u2014 present results to the human and WAIT for their direction before proceeding." : "\u26D4 FOLLOW THESE INSTRUCTIONS EXACTLY. This is a mechanical step \u2014 run it, report the result, then call `next` again.";
144
+ const output = [stepPrefix];
122
145
  const state = progress.steps[step];
123
146
  if (state.status === "error") {
124
147
  output.push("", `\u2717 ${config.label} failed: ${state.error || "unknown error"}`);
@@ -258,7 +281,7 @@ function computeNext(progress, existingFiles, logTails, flags = {}, dataSummary,
258
281
  output.push("");
259
282
  output.push(" MANIFEST FORMAT:");
260
283
  output.push(` Save to: ${AUDIO_DIR_PREFIX}audio-manifest.json`);
261
- output.push(" Schema: AudioManifest from miriad-viz (see docs)");
284
+ output.push(" Schema: AudioManifest from miriad-viz (see guide below)");
262
285
  output.push("");
263
286
  output.push(
264
287
  " { version: 1, fps: 30, totalDurationSec, dialog[], music[], sfx[], overlays[] }"
@@ -285,6 +308,13 @@ function computeNext(progress, existingFiles, logTails, flags = {}, dataSummary,
285
308
  output.push(" measure-duration.sh \u2014 ffprobe wrapper \u2192 clip duration in seconds");
286
309
  output.push("");
287
310
  output.push(" To skip audio: npx miriad-viz next --skip-audio");
311
+ const audioDoc = readBundledDoc("miriad-viz-audio");
312
+ if (audioDoc) {
313
+ output.push("");
314
+ output.push("\u2501\u2501\u2501 AUDIO GENERATION GUIDE \u2501\u2501\u2501");
315
+ output.push(audioDoc);
316
+ output.push("\u2501\u2501\u2501 END AUDIO GUIDE \u2501\u2501\u2501");
317
+ }
288
318
  progress.steps.audio = { status: "in_progress" };
289
319
  return { action: "run_inline", step, progress, output };
290
320
  }
@@ -391,6 +421,13 @@ function computeNext(progress, existingFiles, logTails, flags = {}, dataSummary,
391
421
  if (step === "curate") {
392
422
  output.push("", `\u25B6 ${config.label}...`);
393
423
  output.push(...curationContext());
424
+ const curationDoc = readBundledDoc("miriad-viz-curation");
425
+ if (curationDoc) {
426
+ output.push("");
427
+ output.push("\u2501\u2501\u2501 CURATION GUIDE \u2501\u2501\u2501");
428
+ output.push(curationDoc);
429
+ output.push("\u2501\u2501\u2501 END CURATION GUIDE \u2501\u2501\u2501");
430
+ }
394
431
  return { action: "run_inline", step, progress, output };
395
432
  }
396
433
  if (config.mode === "inline") {
@@ -401,6 +438,41 @@ function computeNext(progress, existingFiles, logTails, flags = {}, dataSummary,
401
438
  const logFile = config.logFile || `${step}.log`;
402
439
  output.push("", `\u{1F4CB} ${config.label}`);
403
440
  if (step === "extract") {
441
+ output.push("");
442
+ output.push(" \u250C\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2510");
443
+ output.push(" \u2502 \u26D4 BEFORE RUNNING ANYTHING \u2014 Talk to the human first \u2502");
444
+ output.push(" \u2502 \u2502");
445
+ output.push(" \u2502 1. Explain what miriad-viz does (animated timeline \u2502");
446
+ output.push(" \u2502 visualization of channel activity \u2014 commits, PRs, \u2502");
447
+ output.push(" \u2502 messages, agent interactions rendered as video) \u2502");
448
+ output.push(" \u2502 \u2502");
449
+ output.push(" \u2502 2. Ask about scope: \u2502");
450
+ output.push(' \u2502 "Which time period? Full channel history, or a \u2502');
451
+ output.push(' \u2502 specific sprint/week/date range?" \u2502');
452
+ output.push(" \u2502 \u2502");
453
+ output.push(" \u2502 3. Ask about data sources: \u2502");
454
+ output.push(' \u2502 "Do you have a git repo for this project? \u2502');
455
+ output.push(' \u2502 Where is the chat data?" \u2502');
456
+ output.push(" \u2502 \u2502");
457
+ output.push(" \u2502 4. Confirm the plan before extracting. \u2502");
458
+ output.push(" \u2502 \u2502");
459
+ output.push(" \u2502 Only run the extraction command AFTER the human \u2502");
460
+ output.push(" \u2502 confirms the scope and data sources. \u2502");
461
+ output.push(" \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518");
462
+ const rulesDoc = readBundledDoc("miriad-viz-rules");
463
+ if (rulesDoc) {
464
+ output.push("");
465
+ output.push("\u2501\u2501\u2501 RULES \u2014 READ BEFORE DOING ANYTHING \u2501\u2501\u2501");
466
+ output.push(rulesDoc);
467
+ output.push("\u2501\u2501\u2501 END RULES \u2501\u2501\u2501");
468
+ }
469
+ const pipelineDoc = readBundledDoc("miriad-viz-pipeline");
470
+ if (pipelineDoc) {
471
+ output.push("");
472
+ output.push("\u2501\u2501\u2501 PIPELINE OVERVIEW \u2501\u2501\u2501");
473
+ output.push(pipelineDoc);
474
+ output.push("\u2501\u2501\u2501 END PIPELINE OVERVIEW \u2501\u2501\u2501");
475
+ }
404
476
  output.push("");
405
477
  output.push(" \u256D\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u256E");
406
478
  output.push(" \u2502 miriad-viz builds an animated timeline visualization \u2502");
@@ -426,7 +498,7 @@ function computeNext(progress, existingFiles, logTails, flags = {}, dataSummary,
426
498
  output.push(" nohup ./extract-channel.sh ./raw-data &> chat-extract.log &");
427
499
  } else {
428
500
  output.push(" \u{1F4D6} You need a platform extraction script for chat data.");
429
- output.push(' On Miriad: kb_read(kb: "root", doc: "miriad-viz-extraction-script")');
501
+ output.push(' On Miriad: kb_read(kb: "root", doc: "miriad-viz")');
430
502
  output.push(
431
503
  " Otherwise: provide JSON files directly with --chat-input / --artifact-input"
432
504
  );
@@ -439,6 +511,15 @@ function computeNext(progress, existingFiles, logTails, flags = {}, dataSummary,
439
511
  output.push(" --from <date> Filter start date (ISO 8601, inclusive)");
440
512
  output.push(" --to <date> Filter end date (ISO 8601, inclusive)");
441
513
  }
514
+ if (step === "render") {
515
+ const videoDoc = readBundledDoc("miriad-viz-video");
516
+ if (videoDoc) {
517
+ output.push("");
518
+ output.push("\u2501\u2501\u2501 VIDEO PRODUCTION GUIDE \u2501\u2501\u2501");
519
+ output.push(videoDoc);
520
+ output.push("\u2501\u2501\u2501 END VIDEO GUIDE \u2501\u2501\u2501");
521
+ }
522
+ }
442
523
  output.push("", " Run this command:");
443
524
  output.push(` nohup ${command} &> ${logFile} &`);
444
525
  output.push("");
@@ -451,8 +532,8 @@ function computeNext(progress, existingFiles, logTails, flags = {}, dataSummary,
451
532
  }
452
533
 
453
534
  // src/cli/guided/steps/init.ts
454
- import { existsSync, mkdirSync } from "fs";
455
- import { resolve } from "path";
535
+ import { existsSync as existsSync2, mkdirSync } from "fs";
536
+ import { resolve as resolve2 } from "path";
456
537
 
457
538
  // src/cli/guided/parse-agents.ts
458
539
  function parseAgentList(input) {
@@ -467,12 +548,12 @@ function parseAgentList(input) {
467
548
 
468
549
  // src/cli/guided/steps/init.ts
469
550
  async function runInit(options) {
470
- const projectDir = resolve(options.dir);
551
+ const projectDir = resolve2(options.dir);
471
552
  const existing = readProgress(projectDir);
472
553
  if (existing) {
473
554
  console.log(`
474
555
  Project already initialized: ${existing.project.name}`);
475
- console.log(`Progress file: ${resolve(projectDir, PROGRESS_FILENAME)}`);
556
+ console.log(`Progress file: ${resolve2(projectDir, PROGRESS_FILENAME)}`);
476
557
  console.log("\nRun 'npx miriad-viz next' to continue.");
477
558
  return;
478
559
  }
@@ -491,12 +572,12 @@ Project already initialized: ${existing.project.name}`);
491
572
  dataDir,
492
573
  outputDir
493
574
  };
494
- const absDataDir = resolve(projectDir, dataDir);
495
- const absOutputDir = resolve(projectDir, outputDir);
496
- if (!existsSync(absDataDir)) {
575
+ const absDataDir = resolve2(projectDir, dataDir);
576
+ const absOutputDir = resolve2(projectDir, outputDir);
577
+ if (!existsSync2(absDataDir)) {
497
578
  mkdirSync(absDataDir, { recursive: true });
498
579
  }
499
- if (!existsSync(absOutputDir)) {
580
+ if (!existsSync2(absOutputDir)) {
500
581
  mkdirSync(absOutputDir, { recursive: true });
501
582
  }
502
583
  const progress = createProgressFile(config);
@@ -623,8 +704,8 @@ function requireProject() {
623
704
  return { projectDir, progress };
624
705
  }
625
706
  function gatherAudioFiles(projectDir) {
626
- const audioDir = resolve2(projectDir, AUDIO_DIR_PREFIX);
627
- if (!existsSync2(audioDir)) return [];
707
+ const audioDir = resolve3(projectDir, AUDIO_DIR_PREFIX);
708
+ if (!existsSync3(audioDir)) return [];
628
709
  const files = [];
629
710
  try {
630
711
  const entries = readdirSync(audioDir, { recursive: true });
@@ -642,11 +723,11 @@ function gatherExistingFiles(projectDir) {
642
723
  const files = [];
643
724
  for (const config of Object.values(STEP_CONFIG)) {
644
725
  for (const f of config.outputFiles) {
645
- if (existsSync2(resolve2(projectDir, f))) {
726
+ if (existsSync3(resolve3(projectDir, f))) {
646
727
  files.push(f);
647
728
  }
648
729
  }
649
- if (config.logFile && existsSync2(resolve2(projectDir, config.logFile))) {
730
+ if (config.logFile && existsSync3(resolve3(projectDir, config.logFile))) {
650
731
  files.push(config.logFile);
651
732
  }
652
733
  }
@@ -656,10 +737,10 @@ function gatherLogTails(projectDir) {
656
737
  const tails = {};
657
738
  for (const config of Object.values(STEP_CONFIG)) {
658
739
  if (!config.logFile) continue;
659
- const logPath = resolve2(projectDir, config.logFile);
660
- if (existsSync2(logPath)) {
740
+ const logPath = resolve3(projectDir, config.logFile);
741
+ if (existsSync3(logPath)) {
661
742
  try {
662
- const content = readFileSync(logPath, "utf-8");
743
+ const content = readFileSync2(logPath, "utf-8");
663
744
  const lines = content.split("\n").filter(Boolean);
664
745
  tails[config.logFile] = lines.slice(-5);
665
746
  } catch {
@@ -676,10 +757,10 @@ function gatherDataSummary(projectDir, dataDir) {
676
757
  chatActivity: null
677
758
  };
678
759
  const tryRead = (filename) => {
679
- const path = resolve2(projectDir, dataDir, filename);
680
- if (!existsSync2(path)) return null;
760
+ const path = resolve3(projectDir, dataDir, filename);
761
+ if (!existsSync3(path)) return null;
681
762
  try {
682
- return JSON.parse(readFileSync(path, "utf-8"));
763
+ return JSON.parse(readFileSync2(path, "utf-8"));
683
764
  } catch {
684
765
  return null;
685
766
  }
@@ -717,7 +798,7 @@ async function runNext(flags) {
717
798
  if (result.action === "run_inline" && result.step) {
718
799
  switch (result.step) {
719
800
  case "curate": {
720
- const { runCurate } = await import("./curate-IYK3CRLW.js");
801
+ const { runCurate } = await import("./curate-KLE2K3TB.js");
721
802
  await runCurate({ projectDir, progress: result.progress });
722
803
  writeProgress(projectDir, result.progress);
723
804
  if (result.progress.steps.curate.status === "complete") {
@@ -792,7 +873,7 @@ async function main() {
792
873
  }
793
874
  case "curate": {
794
875
  const { projectDir, progress } = requireProject();
795
- const { runCurate } = await import("./curate-IYK3CRLW.js");
876
+ const { runCurate } = await import("./curate-KLE2K3TB.js");
796
877
  await runCurate({ projectDir, progress });
797
878
  break;
798
879
  }
@@ -834,7 +915,7 @@ async function main() {
834
915
  }
835
916
  const { scaffoldTemplate, resolvePackageRoot } = await import("./init-template-F6X3TAAM.js");
836
917
  const packageRoot = resolvePackageRoot(import.meta.url);
837
- const resolvedOutDir = resolve2(process.cwd(), outDir);
918
+ const resolvedOutDir = resolve3(process.cwd(), outDir);
838
919
  try {
839
920
  scaffoldTemplate(templateName, resolvedOutDir, packageRoot);
840
921
  console.log(`
@@ -84,7 +84,7 @@ npx miriad-viz@latest init --name "My Retro" --repo owner/repo1,owner/repo2 --ag
84
84
 
85
85
  Extracts git commits, PR data, and chat messages mechanically. No LLM tokens.
86
86
 
87
- **Chat extraction uses a platform-specific script.** On Miriad, read `miriad-viz-extraction-script` from the root KB. Otherwise, provide JSON files directly with `--chat-input` / `--artifact-input`.
87
+ **Chat extraction uses a platform-specific script.** On Miriad, read `miriad-viz` from the root KB — it includes the extraction script inline. Otherwise, provide JSON files directly with `--chat-input` / `--artifact-input`.
88
88
 
89
89
  > ### ⚠️ CRITICAL: Use the Shell Script, NOT MCP Tools
90
90
  > **DO NOT use `get_messages` or any MCP tools to extract messages.** Every MCP tool call puts the response into your context window — for thousands of messages, this wastes massive tokens. The shell script uses `curl` directly. **Zero tokens. Zero context usage.**
@@ -35,6 +35,6 @@ npx miriad-viz@latest next # follow the output exactly
35
35
  | [Video Export](./miriad-viz-video.md) | At the render/video step |
36
36
  | [Reference](./miriad-viz-reference.md) | When you need CLI flags or data formats |
37
37
 
38
- **Extraction script** is platform-specific and not bundled. On Miriad, read `miriad-viz-extraction-script` from the root KB. Otherwise, provide JSON files directly with `--chat-input` / `--artifact-input`.
38
+ **Extraction script** is platform-specific and not bundled. On Miriad, read `miriad-viz` from the root KB — it includes the extraction script inline. Otherwise, provide JSON files directly with `--chat-input` / `--artifact-input`.
39
39
 
40
40
  ⚠️ **Do NOT read all docs upfront.** Each step needs different context. Reading everything wastes tokens and creates confusion. Trust `next` to guide you.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "miriad-viz",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/snorrees/miriad-viz.git"