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.
|
|
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.
|
|
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
|
|
13
|
-
import { resolve as
|
|
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
|
|
120
|
-
|
|
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
|
|
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
|
|
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 =
|
|
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: ${
|
|
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 =
|
|
495
|
-
const absOutputDir =
|
|
496
|
-
if (!
|
|
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 (!
|
|
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 =
|
|
627
|
-
if (!
|
|
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 (
|
|
726
|
+
if (existsSync3(resolve3(projectDir, f))) {
|
|
646
727
|
files.push(f);
|
|
647
728
|
}
|
|
648
729
|
}
|
|
649
|
-
if (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 =
|
|
660
|
-
if (
|
|
740
|
+
const logPath = resolve3(projectDir, config.logFile);
|
|
741
|
+
if (existsSync3(logPath)) {
|
|
661
742
|
try {
|
|
662
|
-
const content =
|
|
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 =
|
|
680
|
-
if (!
|
|
760
|
+
const path = resolve3(projectDir, dataDir, filename);
|
|
761
|
+
if (!existsSync3(path)) return null;
|
|
681
762
|
try {
|
|
682
|
-
return JSON.parse(
|
|
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-
|
|
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-
|
|
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 =
|
|
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
|
|
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.**
|
package/docs/miriad-viz.md
CHANGED
|
@@ -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
|
|
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.
|