Initialize narratio Go module and CLI scaffold
This commit is contained in:
20
internal/adapters/analyzer/runner.go
Normal file
20
internal/adapters/analyzer/runner.go
Normal file
@@ -0,0 +1,20 @@
|
||||
// Package analyzer declares the adapter contract for artifact analysis generation.
|
||||
package analyzer
|
||||
|
||||
import "context"
|
||||
|
||||
// Runner is a placeholder adapter interface for session artifact generation.
|
||||
type Runner interface {
|
||||
Run(ctx context.Context, req AnalysisRequest) (AnalysisResult, error)
|
||||
}
|
||||
|
||||
// AnalysisRequest is a placeholder analyzer input.
|
||||
type AnalysisRequest struct {
|
||||
ProcessedTranscriptPath string
|
||||
OutputDir string
|
||||
}
|
||||
|
||||
// AnalysisResult is a placeholder analyzer output.
|
||||
type AnalysisResult struct {
|
||||
ArtifactPaths []string
|
||||
}
|
||||
20
internal/adapters/audita/runner.go
Normal file
20
internal/adapters/audita/runner.go
Normal file
@@ -0,0 +1,20 @@
|
||||
// Package audita declares the adapter contract for transcript polishing.
|
||||
package audita
|
||||
|
||||
import "context"
|
||||
|
||||
// Runner is a placeholder adapter interface for audita invocation.
|
||||
type Runner interface {
|
||||
Run(ctx context.Context, req PolishRequest) (PolishResult, error)
|
||||
}
|
||||
|
||||
// PolishRequest is a placeholder polish input.
|
||||
type PolishRequest struct {
|
||||
MergedTranscriptPath string
|
||||
OutputPath string
|
||||
}
|
||||
|
||||
// PolishResult is a placeholder polish output.
|
||||
type PolishResult struct {
|
||||
ProcessedPath string
|
||||
}
|
||||
15
internal/adapters/notify/sender.go
Normal file
15
internal/adapters/notify/sender.go
Normal file
@@ -0,0 +1,15 @@
|
||||
// Package notify declares the adapter contract for run notifications.
|
||||
package notify
|
||||
|
||||
import "context"
|
||||
|
||||
// Sender is a placeholder adapter interface for notifications.
|
||||
type Sender interface {
|
||||
Send(ctx context.Context, msg Message) error
|
||||
}
|
||||
|
||||
// Message is a placeholder notification payload.
|
||||
type Message struct {
|
||||
Subject string
|
||||
Body string
|
||||
}
|
||||
20
internal/adapters/seriatim/runner.go
Normal file
20
internal/adapters/seriatim/runner.go
Normal file
@@ -0,0 +1,20 @@
|
||||
// Package seriatim declares the adapter contract for transcript merge execution.
|
||||
package seriatim
|
||||
|
||||
import "context"
|
||||
|
||||
// Runner is a placeholder adapter interface for seriatim invocation.
|
||||
type Runner interface {
|
||||
Run(ctx context.Context, req MergeRequest) (MergeResult, error)
|
||||
}
|
||||
|
||||
// MergeRequest is a placeholder merge input.
|
||||
type MergeRequest struct {
|
||||
TranscriptPaths []string
|
||||
OutputPath string
|
||||
}
|
||||
|
||||
// MergeResult is a placeholder merge output.
|
||||
type MergeResult struct {
|
||||
MergedPath string
|
||||
}
|
||||
20
internal/adapters/whisperx/client.go
Normal file
20
internal/adapters/whisperx/client.go
Normal file
@@ -0,0 +1,20 @@
|
||||
// Package whisperx declares the adapter contract for WhisperX transcription.
|
||||
package whisperx
|
||||
|
||||
import "context"
|
||||
|
||||
// Client is a placeholder adapter interface for WhisperX interactions.
|
||||
type Client interface {
|
||||
Transcribe(ctx context.Context, req TranscriptionRequest) (TranscriptionResult, error)
|
||||
}
|
||||
|
||||
// TranscriptionRequest is a placeholder transcription input.
|
||||
type TranscriptionRequest struct {
|
||||
Speaker string
|
||||
AudioPath string
|
||||
}
|
||||
|
||||
// TranscriptionResult is a placeholder transcription output.
|
||||
type TranscriptionResult struct {
|
||||
TranscriptPath string
|
||||
}
|
||||
26
internal/app/app.go
Normal file
26
internal/app/app.go
Normal file
@@ -0,0 +1,26 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"log/slog"
|
||||
|
||||
"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/seriatim"
|
||||
"gitea.maximumdirect.net/eric/narratio/internal/adapters/whisperx"
|
||||
"gitea.maximumdirect.net/eric/narratio/internal/artifacts"
|
||||
"gitea.maximumdirect.net/eric/narratio/internal/config"
|
||||
)
|
||||
|
||||
// Env is the shared dependency container passed to orchestrator components.
|
||||
type Env struct {
|
||||
Config *config.Config
|
||||
ArtifactStore artifacts.Store
|
||||
Logger *slog.Logger
|
||||
|
||||
WhisperX whisperx.Client
|
||||
Seriatim seriatim.Runner
|
||||
Audita audita.Runner
|
||||
Analyzer analyzer.Runner
|
||||
Notifier notify.Sender
|
||||
}
|
||||
56
internal/app/commands.go
Normal file
56
internal/app/commands.go
Normal file
@@ -0,0 +1,56 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var supportedCommands = []string{"run", "plan", "status", "resume", "run-stage"}
|
||||
|
||||
// Execute dispatches CLI commands and returns a process exit code.
|
||||
func Execute(args []string, stdout, stderr io.Writer) int {
|
||||
if len(args) == 0 {
|
||||
printUsage(stderr)
|
||||
return 1
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
cmd := args[0]
|
||||
cmdArgs := args[1:]
|
||||
|
||||
var err error
|
||||
switch cmd {
|
||||
case "run":
|
||||
err = Run(ctx, cmdArgs, stdout)
|
||||
case "plan":
|
||||
err = Plan(ctx, cmdArgs, stdout)
|
||||
case "status":
|
||||
err = Status(ctx, cmdArgs, stdout)
|
||||
case "resume":
|
||||
err = Resume(ctx, cmdArgs, stdout)
|
||||
case "run-stage":
|
||||
err = RunStage(ctx, cmdArgs, stdout)
|
||||
default:
|
||||
fmt.Fprintf(stderr, "unknown command: %q\n\n", cmd)
|
||||
printUsage(stderr)
|
||||
return 1
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
fmt.Fprintf(stderr, "%v\n", err)
|
||||
return 1
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
func printUsage(w io.Writer) {
|
||||
fmt.Fprintf(w, "Usage: narratio <%s>\n", strings.Join(supportedCommands, "|"))
|
||||
}
|
||||
|
||||
func placeholder(out io.Writer, command string) error {
|
||||
_, err := fmt.Fprintf(out, "narratio %s: not yet implemented\n", command)
|
||||
return err
|
||||
}
|
||||
75
internal/app/commands_test.go
Normal file
75
internal/app/commands_test.go
Normal file
@@ -0,0 +1,75 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestExecuteValidCommands(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
args []string
|
||||
wantOut string
|
||||
}{
|
||||
{name: "run", args: []string{"run"}, wantOut: "narratio run: not yet implemented"},
|
||||
{name: "plan", args: []string{"plan"}, wantOut: "narratio plan: not yet implemented"},
|
||||
{name: "status", args: []string{"status"}, wantOut: "narratio status: not yet implemented"},
|
||||
{name: "resume", args: []string{"resume"}, wantOut: "narratio resume: not yet implemented"},
|
||||
{name: "run-stage", args: []string{"run-stage", "polish"}, wantOut: "narratio run-stage: not yet implemented"},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
var stdout bytes.Buffer
|
||||
var stderr bytes.Buffer
|
||||
|
||||
code := Execute(tc.args, &stdout, &stderr)
|
||||
if code != 0 {
|
||||
t.Fatalf("exit code = %d, want 0", code)
|
||||
}
|
||||
if stderr.Len() != 0 {
|
||||
t.Fatalf("stderr = %q, want empty", stderr.String())
|
||||
}
|
||||
if !strings.Contains(stdout.String(), tc.wantOut) {
|
||||
t.Fatalf("stdout = %q, want to contain %q", stdout.String(), tc.wantOut)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestExecuteInvalidCommand(t *testing.T) {
|
||||
var stdout bytes.Buffer
|
||||
var stderr bytes.Buffer
|
||||
|
||||
code := Execute([]string{"bogus"}, &stdout, &stderr)
|
||||
if code == 0 {
|
||||
t.Fatalf("exit code = 0, want non-zero")
|
||||
}
|
||||
if stdout.Len() != 0 {
|
||||
t.Fatalf("stdout = %q, want empty", stdout.String())
|
||||
}
|
||||
out := stderr.String()
|
||||
if !strings.Contains(out, "unknown command") {
|
||||
t.Fatalf("stderr = %q, want unknown command message", out)
|
||||
}
|
||||
if !strings.Contains(out, "Usage: narratio") {
|
||||
t.Fatalf("stderr = %q, want usage message", out)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExecuteMissingCommand(t *testing.T) {
|
||||
var stdout bytes.Buffer
|
||||
var stderr bytes.Buffer
|
||||
|
||||
code := Execute(nil, &stdout, &stderr)
|
||||
if code == 0 {
|
||||
t.Fatalf("exit code = 0, want non-zero")
|
||||
}
|
||||
if stdout.Len() != 0 {
|
||||
t.Fatalf("stdout = %q, want empty", stdout.String())
|
||||
}
|
||||
if !strings.Contains(stderr.String(), "Usage: narratio") {
|
||||
t.Fatalf("stderr = %q, want usage message", stderr.String())
|
||||
}
|
||||
}
|
||||
3
internal/app/doc.go
Normal file
3
internal/app/doc.go
Normal file
@@ -0,0 +1,3 @@
|
||||
// Package app contains CLI command wiring and top-level application orchestration
|
||||
// primitives for narratio.
|
||||
package app
|
||||
11
internal/app/plan.go
Normal file
11
internal/app/plan.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
)
|
||||
|
||||
// Plan is a placeholder for future stage planning behavior.
|
||||
func Plan(_ context.Context, _ []string, out io.Writer) error {
|
||||
return placeholder(out, "plan")
|
||||
}
|
||||
11
internal/app/resume.go
Normal file
11
internal/app/resume.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
)
|
||||
|
||||
// Resume is a placeholder for future resume-from-manifest behavior.
|
||||
func Resume(_ context.Context, _ []string, out io.Writer) error {
|
||||
return placeholder(out, "resume")
|
||||
}
|
||||
11
internal/app/run.go
Normal file
11
internal/app/run.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
)
|
||||
|
||||
// Run is a placeholder for the future end-to-end pipeline execution command.
|
||||
func Run(_ context.Context, _ []string, out io.Writer) error {
|
||||
return placeholder(out, "run")
|
||||
}
|
||||
11
internal/app/run_stage.go
Normal file
11
internal/app/run_stage.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
)
|
||||
|
||||
// RunStage is a placeholder for future single-stage execution behavior.
|
||||
func RunStage(_ context.Context, _ []string, out io.Writer) error {
|
||||
return placeholder(out, "run-stage")
|
||||
}
|
||||
11
internal/app/status.go
Normal file
11
internal/app/status.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
)
|
||||
|
||||
// Status is a placeholder for future manifest status inspection behavior.
|
||||
func Status(_ context.Context, _ []string, out io.Writer) error {
|
||||
return placeholder(out, "status")
|
||||
}
|
||||
24
internal/artifacts/checksum.go
Normal file
24
internal/artifacts/checksum.go
Normal file
@@ -0,0 +1,24 @@
|
||||
package artifacts
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"io"
|
||||
"os"
|
||||
)
|
||||
|
||||
// SHA256File returns the SHA-256 hex digest of a file.
|
||||
func SHA256File(path string) (string, error) {
|
||||
f, err := os.Open(path)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
h := sha256.New()
|
||||
if _, err := io.Copy(h, f); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return hex.EncodeToString(h.Sum(nil)), nil
|
||||
}
|
||||
2
internal/artifacts/doc.go
Normal file
2
internal/artifacts/doc.go
Normal file
@@ -0,0 +1,2 @@
|
||||
// Package artifacts defines artifact references and storage contracts.
|
||||
package artifacts
|
||||
31
internal/artifacts/local.go
Normal file
31
internal/artifacts/local.go
Normal file
@@ -0,0 +1,31 @@
|
||||
package artifacts
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// LocalStore is a placeholder local filesystem artifact store.
|
||||
type LocalStore struct {
|
||||
RootDir string
|
||||
}
|
||||
|
||||
// WriteLocal returns a not-yet-implemented error in the scaffold.
|
||||
func (s *LocalStore) WriteLocal(_ context.Context, _ Ref, _ []byte) error {
|
||||
return fmt.Errorf("artifacts local write: not yet implemented")
|
||||
}
|
||||
|
||||
// ReadLocal returns a not-yet-implemented error in the scaffold.
|
||||
func (s *LocalStore) ReadLocal(_ context.Context, _ Ref) ([]byte, error) {
|
||||
return nil, fmt.Errorf("artifacts local read: not yet implemented")
|
||||
}
|
||||
|
||||
// ExistsLocal returns a not-yet-implemented error in the scaffold.
|
||||
func (s *LocalStore) ExistsLocal(_ context.Context, _ Ref) (bool, error) {
|
||||
return false, fmt.Errorf("artifacts local exists: not yet implemented")
|
||||
}
|
||||
|
||||
// Upload returns a not-yet-implemented error in the scaffold.
|
||||
func (s *LocalStore) Upload(_ context.Context, _ Ref) (string, error) {
|
||||
return "", fmt.Errorf("artifacts local upload: not yet implemented")
|
||||
}
|
||||
8
internal/artifacts/paths.go
Normal file
8
internal/artifacts/paths.go
Normal file
@@ -0,0 +1,8 @@
|
||||
package artifacts
|
||||
|
||||
import "path/filepath"
|
||||
|
||||
// SessionWorkDir returns the work directory for one session.
|
||||
func SessionWorkDir(rootDir, sessionID string) string {
|
||||
return filepath.Join(rootDir, "work", sessionID)
|
||||
}
|
||||
32
internal/artifacts/s3.go
Normal file
32
internal/artifacts/s3.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package artifacts
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// S3Store is a placeholder S3-compatible artifact store.
|
||||
type S3Store struct {
|
||||
Bucket string
|
||||
Prefix string
|
||||
}
|
||||
|
||||
// WriteLocal returns a not-yet-implemented error in the scaffold.
|
||||
func (s *S3Store) WriteLocal(_ context.Context, _ Ref, _ []byte) error {
|
||||
return fmt.Errorf("artifacts s3 write local: not yet implemented")
|
||||
}
|
||||
|
||||
// ReadLocal returns a not-yet-implemented error in the scaffold.
|
||||
func (s *S3Store) ReadLocal(_ context.Context, _ Ref) ([]byte, error) {
|
||||
return nil, fmt.Errorf("artifacts s3 read local: not yet implemented")
|
||||
}
|
||||
|
||||
// ExistsLocal returns a not-yet-implemented error in the scaffold.
|
||||
func (s *S3Store) ExistsLocal(_ context.Context, _ Ref) (bool, error) {
|
||||
return false, fmt.Errorf("artifacts s3 exists local: not yet implemented")
|
||||
}
|
||||
|
||||
// Upload returns a not-yet-implemented error in the scaffold.
|
||||
func (s *S3Store) Upload(_ context.Context, _ Ref) (string, error) {
|
||||
return "", fmt.Errorf("artifacts s3 upload: not yet implemented")
|
||||
}
|
||||
19
internal/artifacts/store.go
Normal file
19
internal/artifacts/store.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package artifacts
|
||||
|
||||
import "context"
|
||||
|
||||
// Ref identifies a pipeline artifact and optional remote location.
|
||||
type Ref struct {
|
||||
Kind string
|
||||
LocalPath string
|
||||
RemoteKey string
|
||||
Checksum string
|
||||
}
|
||||
|
||||
// Store is a placeholder artifact storage abstraction.
|
||||
type Store interface {
|
||||
WriteLocal(ctx context.Context, ref Ref, data []byte) error
|
||||
ReadLocal(ctx context.Context, ref Ref) ([]byte, error)
|
||||
ExistsLocal(ctx context.Context, ref Ref) (bool, error)
|
||||
Upload(ctx context.Context, ref Ref) (string, error)
|
||||
}
|
||||
15
internal/config/config.go
Normal file
15
internal/config/config.go
Normal file
@@ -0,0 +1,15 @@
|
||||
package config
|
||||
|
||||
// Config contains loaded pipeline and session configuration.
|
||||
type Config struct {
|
||||
Pipeline *Pipeline
|
||||
Session *Session
|
||||
}
|
||||
|
||||
// Pipeline represents durable pipeline-level settings.
|
||||
type Pipeline struct{}
|
||||
|
||||
// Session represents per-session inputs and metadata.
|
||||
type Session struct {
|
||||
SessionID string
|
||||
}
|
||||
2
internal/config/doc.go
Normal file
2
internal/config/doc.go
Normal file
@@ -0,0 +1,2 @@
|
||||
// Package config contains pipeline and session configuration contracts.
|
||||
package config
|
||||
8
internal/config/load.go
Normal file
8
internal/config/load.go
Normal file
@@ -0,0 +1,8 @@
|
||||
package config
|
||||
|
||||
import "fmt"
|
||||
|
||||
// Load is a placeholder for strict pipeline/session config decoding.
|
||||
func Load(_ string, _ string) (*Config, error) {
|
||||
return nil, fmt.Errorf("config load: not yet implemented")
|
||||
}
|
||||
8
internal/config/validate.go
Normal file
8
internal/config/validate.go
Normal file
@@ -0,0 +1,8 @@
|
||||
package config
|
||||
|
||||
import "fmt"
|
||||
|
||||
// Validate is a placeholder for configuration validation logic.
|
||||
func Validate(_ *Config) error {
|
||||
return fmt.Errorf("config validation: not yet implemented")
|
||||
}
|
||||
7
internal/contracts/artifact.go
Normal file
7
internal/contracts/artifact.go
Normal file
@@ -0,0 +1,7 @@
|
||||
package contracts
|
||||
|
||||
// ArtifactResult is a placeholder generated artifact contract.
|
||||
type ArtifactResult struct {
|
||||
Schema string `json:"schema"`
|
||||
Path string `json:"path"`
|
||||
}
|
||||
2
internal/contracts/doc.go
Normal file
2
internal/contracts/doc.go
Normal file
@@ -0,0 +1,2 @@
|
||||
// Package contracts defines shared high-level artifact contracts.
|
||||
package contracts
|
||||
7
internal/contracts/session.go
Normal file
7
internal/contracts/session.go
Normal file
@@ -0,0 +1,7 @@
|
||||
package contracts
|
||||
|
||||
// SessionManifest is a placeholder durable session-run contract.
|
||||
type SessionManifest struct {
|
||||
Schema string `json:"schema"`
|
||||
SessionID string `json:"session_id"`
|
||||
}
|
||||
19
internal/contracts/transcript.go
Normal file
19
internal/contracts/transcript.go
Normal file
@@ -0,0 +1,19 @@
|
||||
package contracts
|
||||
|
||||
// SpeakerTranscript is a placeholder transcription artifact contract.
|
||||
type SpeakerTranscript struct {
|
||||
Schema string `json:"schema"`
|
||||
SessionID string `json:"session_id"`
|
||||
}
|
||||
|
||||
// CanonicalTranscript is a placeholder merged transcript contract.
|
||||
type CanonicalTranscript struct {
|
||||
Schema string `json:"schema"`
|
||||
SessionID string `json:"session_id"`
|
||||
}
|
||||
|
||||
// ProcessedTranscript is a placeholder polished transcript contract.
|
||||
type ProcessedTranscript struct {
|
||||
Schema string `json:"schema"`
|
||||
SessionID string `json:"session_id"`
|
||||
}
|
||||
2
internal/logging/doc.go
Normal file
2
internal/logging/doc.go
Normal file
@@ -0,0 +1,2 @@
|
||||
// Package logging provides structured logger construction for narratio.
|
||||
package logging
|
||||
17
internal/logging/logging.go
Normal file
17
internal/logging/logging.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package logging
|
||||
|
||||
import (
|
||||
"io"
|
||||
"log/slog"
|
||||
"os"
|
||||
)
|
||||
|
||||
// NewLogger creates a text slog logger.
|
||||
func NewLogger(out io.Writer, level slog.Level) *slog.Logger {
|
||||
if out == nil {
|
||||
out = os.Stderr
|
||||
}
|
||||
|
||||
handler := slog.NewTextHandler(out, &slog.HandlerOptions{Level: level})
|
||||
return slog.New(handler)
|
||||
}
|
||||
31
internal/logging/logging_test.go
Normal file
31
internal/logging/logging_test.go
Normal file
@@ -0,0 +1,31 @@
|
||||
package logging
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"log/slog"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestNewLoggerWritesOutput(t *testing.T) {
|
||||
var buf bytes.Buffer
|
||||
logger := NewLogger(&buf, slog.LevelInfo)
|
||||
|
||||
if logger == nil {
|
||||
t.Fatal("logger is nil")
|
||||
}
|
||||
|
||||
logger.Info("hello", "component", "test")
|
||||
out := buf.String()
|
||||
if !strings.Contains(out, "hello") {
|
||||
t.Fatalf("output = %q, want to contain message", out)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewLoggerNilWriter(t *testing.T) {
|
||||
logger := NewLogger(nil, slog.LevelInfo)
|
||||
if logger == nil {
|
||||
t.Fatal("logger is nil")
|
||||
}
|
||||
logger.Info("should not panic")
|
||||
}
|
||||
2
internal/manifest/doc.go
Normal file
2
internal/manifest/doc.go
Normal file
@@ -0,0 +1,2 @@
|
||||
// Package manifest defines durable run-state tracking for narratio sessions.
|
||||
package manifest
|
||||
18
internal/manifest/manifest.go
Normal file
18
internal/manifest/manifest.go
Normal file
@@ -0,0 +1,18 @@
|
||||
package manifest
|
||||
|
||||
import "time"
|
||||
|
||||
// StageState tracks status and metadata for one stage execution.
|
||||
type StageState struct {
|
||||
Status StageStatus
|
||||
UpdatedAt time.Time
|
||||
Error string
|
||||
}
|
||||
|
||||
// Manifest is the durable state record for a session run.
|
||||
type Manifest struct {
|
||||
SessionID string
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
Stages map[string]StageState
|
||||
}
|
||||
14
internal/manifest/status.go
Normal file
14
internal/manifest/status.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package manifest
|
||||
|
||||
// StageStatus is the lifecycle state of a pipeline stage.
|
||||
type StageStatus string
|
||||
|
||||
const (
|
||||
StatusPending StageStatus = "pending"
|
||||
StatusRunning StageStatus = "running"
|
||||
StatusSucceeded StageStatus = "succeeded"
|
||||
StatusFailed StageStatus = "failed"
|
||||
StatusSkipped StageStatus = "skipped"
|
||||
StatusStale StageStatus = "stale"
|
||||
StatusInterrupted StageStatus = "interrupted"
|
||||
)
|
||||
27
internal/manifest/store.go
Normal file
27
internal/manifest/store.go
Normal file
@@ -0,0 +1,27 @@
|
||||
package manifest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
// Store is a placeholder interface for manifest persistence.
|
||||
type Store interface {
|
||||
Load(ctx context.Context, sessionID string) (*Manifest, error)
|
||||
Save(ctx context.Context, m *Manifest) error
|
||||
}
|
||||
|
||||
// LocalStore is a placeholder local-filesystem manifest store.
|
||||
type LocalStore struct {
|
||||
RootDir string
|
||||
}
|
||||
|
||||
// Load returns a not-yet-implemented error in the scaffold.
|
||||
func (s *LocalStore) Load(_ context.Context, _ string) (*Manifest, error) {
|
||||
return nil, fmt.Errorf("manifest local load: not yet implemented")
|
||||
}
|
||||
|
||||
// Save returns a not-yet-implemented error in the scaffold.
|
||||
func (s *LocalStore) Save(_ context.Context, _ *Manifest) error {
|
||||
return fmt.Errorf("manifest local save: not yet implemented")
|
||||
}
|
||||
2
internal/stage/doc.go
Normal file
2
internal/stage/doc.go
Normal file
@@ -0,0 +1,2 @@
|
||||
// Package stage defines pipeline stage contracts and placeholder stage types.
|
||||
package stage
|
||||
63
internal/stage/placeholders.go
Normal file
63
internal/stage/placeholders.go
Normal file
@@ -0,0 +1,63 @@
|
||||
package stage
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"gitea.maximumdirect.net/eric/narratio/internal/app"
|
||||
"gitea.maximumdirect.net/eric/narratio/internal/manifest"
|
||||
)
|
||||
|
||||
func notImplemented(name string) error {
|
||||
return fmt.Errorf("stage %q: not yet implemented", name)
|
||||
}
|
||||
|
||||
type Prepare struct{}
|
||||
|
||||
type Transcribe struct{}
|
||||
|
||||
type Normalize struct{}
|
||||
|
||||
type Merge struct{}
|
||||
|
||||
type Polish struct{}
|
||||
|
||||
type Analyze struct{}
|
||||
|
||||
type Archive struct{}
|
||||
|
||||
type Notify struct{}
|
||||
|
||||
func (Prepare) Name() string { return "prepare" }
|
||||
func (Transcribe) Name() string { return "transcribe" }
|
||||
func (Normalize) Name() string { return "normalize" }
|
||||
func (Merge) Name() string { return "merge" }
|
||||
func (Polish) Name() string { return "polish" }
|
||||
func (Analyze) Name() string { return "analyze" }
|
||||
func (Archive) Name() string { return "archive" }
|
||||
func (Notify) Name() string { return "notify" }
|
||||
|
||||
func (s Prepare) Run(_ context.Context, _ *app.Env, _ *manifest.Manifest) (*Result, error) {
|
||||
return nil, notImplemented(s.Name())
|
||||
}
|
||||
func (s Transcribe) Run(_ context.Context, _ *app.Env, _ *manifest.Manifest) (*Result, error) {
|
||||
return nil, notImplemented(s.Name())
|
||||
}
|
||||
func (s Normalize) Run(_ context.Context, _ *app.Env, _ *manifest.Manifest) (*Result, error) {
|
||||
return nil, notImplemented(s.Name())
|
||||
}
|
||||
func (s Merge) Run(_ context.Context, _ *app.Env, _ *manifest.Manifest) (*Result, error) {
|
||||
return nil, notImplemented(s.Name())
|
||||
}
|
||||
func (s Polish) Run(_ context.Context, _ *app.Env, _ *manifest.Manifest) (*Result, error) {
|
||||
return nil, notImplemented(s.Name())
|
||||
}
|
||||
func (s Analyze) Run(_ context.Context, _ *app.Env, _ *manifest.Manifest) (*Result, error) {
|
||||
return nil, notImplemented(s.Name())
|
||||
}
|
||||
func (s Archive) Run(_ context.Context, _ *app.Env, _ *manifest.Manifest) (*Result, error) {
|
||||
return nil, notImplemented(s.Name())
|
||||
}
|
||||
func (s Notify) Run(_ context.Context, _ *app.Env, _ *manifest.Manifest) (*Result, error) {
|
||||
return nil, notImplemented(s.Name())
|
||||
}
|
||||
21
internal/stage/stage.go
Normal file
21
internal/stage/stage.go
Normal file
@@ -0,0 +1,21 @@
|
||||
package stage
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"gitea.maximumdirect.net/eric/narratio/internal/app"
|
||||
"gitea.maximumdirect.net/eric/narratio/internal/artifacts"
|
||||
"gitea.maximumdirect.net/eric/narratio/internal/manifest"
|
||||
)
|
||||
|
||||
// Stage is the pipeline unit contract.
|
||||
type Stage interface {
|
||||
Name() string
|
||||
Run(ctx context.Context, env *app.Env, m *manifest.Manifest) (*Result, error)
|
||||
}
|
||||
|
||||
// Result is the declared output of a stage execution.
|
||||
type Result struct {
|
||||
Outputs []artifacts.Ref
|
||||
Metadata map[string]any
|
||||
}
|
||||
Reference in New Issue
Block a user