Implement Scriptorium session recap analysis

This commit is contained in:
2026-05-06 21:26:54 +00:00
parent f94590f70e
commit 1ea24accd1
7 changed files with 901 additions and 38 deletions

View File

@@ -8,9 +8,9 @@ import (
"path/filepath"
"strings"
"gitea.maximumdirect.net/eric/narratio/internal/adapters/analyzer"
"gitea.maximumdirect.net/eric/narratio/internal/adapters/audita"
"gitea.maximumdirect.net/eric/narratio/internal/adapters/notify"
"gitea.maximumdirect.net/eric/narratio/internal/adapters/scriptorium"
"gitea.maximumdirect.net/eric/narratio/internal/adapters/seriatim"
"gitea.maximumdirect.net/eric/narratio/internal/adapters/storage"
"gitea.maximumdirect.net/eric/narratio/internal/adapters/whisperx"
@@ -72,8 +72,8 @@ func executeStages(ctx context.Context, cfg *config.Config, stages []stage.Stage
}
env.Audita = runner
}
if env.Analyzer == nil {
env.Analyzer = &analyzer.NoopRunner{}
if env.Scriptorium == nil {
env.Scriptorium = scriptorium.NewSubprocessRunner()
}
if env.Storage == nil {
env.Storage = &storage.NoopBackend{}

View File

@@ -9,9 +9,9 @@ import (
"testing"
"time"
"gitea.maximumdirect.net/eric/narratio/internal/adapters/analyzer"
"gitea.maximumdirect.net/eric/narratio/internal/adapters/audita"
"gitea.maximumdirect.net/eric/narratio/internal/adapters/notify"
"gitea.maximumdirect.net/eric/narratio/internal/adapters/scriptorium"
"gitea.maximumdirect.net/eric/narratio/internal/adapters/seriatim"
"gitea.maximumdirect.net/eric/narratio/internal/adapters/storage"
"gitea.maximumdirect.net/eric/narratio/internal/adapters/whisperx"
@@ -114,6 +114,15 @@ func TestExecuteStagesPlaceholderSuccessUpdatesManifest(t *testing.T) {
}
continue
}
if name == "analyze" {
if sr.Metadata == nil || sr.Metadata["stage"] != "analyze" {
t.Fatalf("analyze metadata missing stage=analyze: %#v", sr.Metadata)
}
if sr.Metadata["skipped"] != true {
t.Fatalf("analyze metadata missing skipped=true when scriptorium is unconfigured: %#v", sr.Metadata)
}
continue
}
if sr.Metadata == nil || sr.Metadata["placeholder"] != true {
t.Fatalf("stage %q missing placeholder metadata", name)
}
@@ -284,7 +293,7 @@ func TestAdapterBackedStageFailureMarksManifestFailed(t *testing.T) {
{name: "transcribe", env: &Env{WhisperX: &whisperx.FakeClient{Err: errors.New("transcribe fail")}}},
{name: "merge", env: &Env{Seriatim: &seriatim.FakeRunner{Err: errors.New("merge fail")}}},
{name: "polish", env: &Env{Audita: &audita.FakeRunner{Err: errors.New("polish fail")}}},
{name: "analyze", env: &Env{Analyzer: &analyzer.FakeRunner{Err: errors.New("analyze fail")}}},
{name: "analyze", env: &Env{Scriptorium: &scriptorium.FakeRunner{RunErr: errors.New("analyze fail")}}},
{name: "archive", env: &Env{Storage: &storage.FakeBackend{Err: errors.New("archive fail")}}},
{name: "notify", env: &Env{Notifier: &notify.FakeSender{Err: errors.New("notify fail")}}},
}
@@ -347,6 +356,29 @@ func TestAdapterBackedStageFailureMarksManifestFailed(t *testing.T) {
t.Fatalf("write glossary: %v", err)
}
}
if tc.name == "analyze" {
paths, ensureErr := artifactStore.EnsureLayout(cfg.Session.SessionID)
if ensureErr != nil {
t.Fatalf("EnsureLayout() error = %v", ensureErr)
}
if err := os.WriteFile(filepath.Join(paths.TranscriptsDir, "processed.json"), []byte(`{"segments":[]}`), 0o644); err != nil {
t.Fatalf("write processed transcript: %v", err)
}
cfg.Pipeline.Scriptorium = &config.ScriptoriumConfig{
Binary: "scriptorium",
Timeout: "10m",
Artifacts: map[string]config.ScriptoriumArtifactConfig{
"session_recap": {
Enabled: true,
PromptID: "dnd.session_recap",
OutputPath: "artifacts/session_recap.md",
Inputs: map[string]config.ScriptoriumInputConfig{
"transcript": {Source: "processed_transcript", Required: true},
},
},
},
}
}
_, runErr := executeStages(context.Background(), cfg, []stage.Stage{selected}, RunOptions{Env: tc.env})
if runErr == nil {