Compare commits
4 Commits
5edb24a9c1
...
8703793b0c
| Author | SHA1 | Date | |
|---|---|---|---|
| 8703793b0c | |||
| 4cb4943a57 | |||
| c6c747e94d | |||
| 2bbf13e739 |
@@ -2,7 +2,8 @@
|
|||||||
|
|
||||||
## Status
|
## Status
|
||||||
|
|
||||||
Ready for implementation. No implementation work described here has started.
|
Completed on 2026-07-27. The framework characterization baseline is complete,
|
||||||
|
and Migration Step 4 is the next planned work.
|
||||||
|
|
||||||
## Objective
|
## Objective
|
||||||
|
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
## Status
|
## Status
|
||||||
|
|
||||||
Accepted plan. Steps 1 and 2 are complete. Steps 3 through 9 remain proposed
|
Accepted plan. Steps 1 through 3 are complete. Steps 4 through 9 remain
|
||||||
and are not yet implemented.
|
proposed and are not yet implemented.
|
||||||
|
|
||||||
## Objective
|
## Objective
|
||||||
|
|
||||||
@@ -145,6 +145,11 @@ Preserve coverage of:
|
|||||||
**Gate:** Current framework and adapter contracts are represented by passing
|
**Gate:** Current framework and adapter contracts are represented by passing
|
||||||
tests sufficient to detect behavioral regressions during the split.
|
tests sufficient to detect behavioral regressions during the split.
|
||||||
|
|
||||||
|
**Gate status:** Complete as of 2026-07-27. The framework contract corpus,
|
||||||
|
public `Engine` characterization, ownership audit, full test and vet suites,
|
||||||
|
temporary executable build, and maintained offline examples passed. Step 4 is
|
||||||
|
next.
|
||||||
|
|
||||||
### Step 4: Make Scriptorium Adapters Consume The Public Facade
|
### Step 4: Make Scriptorium Adapters Consume The Public Facade
|
||||||
|
|
||||||
Within the current repository, refactor the CLI and HTTP adapters to use the
|
Within the current repository, refactor the CLI and HTTP adapters to use the
|
||||||
|
|||||||
@@ -2,8 +2,9 @@
|
|||||||
|
|
||||||
## Status
|
## Status
|
||||||
|
|
||||||
Accepted scope. Implementation has not started. The ordered execution plan is
|
Completed on 2026-07-27. The target state below is characterized by the
|
||||||
in [implementation.md](implementation.md).
|
passing baseline; its ordered implementation record is in
|
||||||
|
[implementation.md](implementation.md).
|
||||||
|
|
||||||
## Purpose
|
## Purpose
|
||||||
|
|
||||||
@@ -38,7 +39,7 @@ injected-client behavior, and reserved provider parameters.
|
|||||||
|
|
||||||
## Target State
|
## Target State
|
||||||
|
|
||||||
At completion:
|
The completed baseline provides:
|
||||||
|
|
||||||
- tests destined for Promptkit use only Promptkit-destined testdata or
|
- tests destined for Promptkit use only Promptkit-destined testdata or
|
||||||
fixtures generated within the test;
|
fixtures generated within the test;
|
||||||
@@ -165,13 +166,13 @@ Step 3 is complete when:
|
|||||||
- the full roadmap behavior list has a clear, non-duplicative test owner;
|
- the full roadmap behavior list has a clear, non-duplicative test owner;
|
||||||
- tests that require Step 4 rewrites are explicitly identified;
|
- tests that require Step 4 rewrites are explicitly identified;
|
||||||
- no production behavior or public API changed;
|
- no production behavior or public API changed;
|
||||||
- all validation in Stage 5 passes; and
|
- all required validation passes; and
|
||||||
- the main migration roadmap records the Step 3 gate as complete.
|
- the main migration roadmap records the Step 3 gate as complete.
|
||||||
|
|
||||||
Migration Step 4 must not begin until these criteria are satisfied.
|
Migration Step 4 must not begin until these criteria are satisfied.
|
||||||
|
|
||||||
## Lifecycle
|
## Lifecycle
|
||||||
|
|
||||||
This is a temporary implementation roadmap. Once Step 3 is complete and its
|
This completed implementation roadmap remains the concise characterization
|
||||||
gate status is recorded in the main migration roadmap, this file may be removed;
|
record for the migration. Repository history retains the detailed implementation
|
||||||
repository history retains the detailed implementation record.
|
record.
|
||||||
|
|||||||
760
engine_test.go
760
engine_test.go
File diff suppressed because it is too large
Load Diff
@@ -1,127 +0,0 @@
|
|||||||
package usecase
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"path/filepath"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"gitea.maximumdirect.net/eric/scriptorium/internal/artifact"
|
|
||||||
"gitea.maximumdirect.net/eric/scriptorium/internal/domain"
|
|
||||||
"gitea.maximumdirect.net/eric/scriptorium/internal/profile"
|
|
||||||
"gitea.maximumdirect.net/eric/scriptorium/internal/prompt"
|
|
||||||
"gitea.maximumdirect.net/eric/scriptorium/internal/promptdef"
|
|
||||||
"gitea.maximumdirect.net/eric/scriptorium/internal/validate"
|
|
||||||
)
|
|
||||||
|
|
||||||
type integrationLLM struct{}
|
|
||||||
|
|
||||||
func (f *integrationLLM) Generate(ctx context.Context, req domain.GenerateRequest) (*domain.GenerateResponse, error) {
|
|
||||||
lastIntegrationRequest = req
|
|
||||||
return &domain.GenerateResponse{
|
|
||||||
Content: `{"summary":"Party discovered a captive scout beneath the tower.","events":[{"title":"Scout found in cellar","type":"discovery","notes":"Scout requested rescue from goblin raiders."}]}`,
|
|
||||||
Usage: domain.TokenUsage{
|
|
||||||
PromptTokens: 42,
|
|
||||||
CompletionTokens: 36,
|
|
||||||
TotalTokens: 78,
|
|
||||||
},
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
var lastIntegrationRequest domain.GenerateRequest
|
|
||||||
|
|
||||||
func TestRunnerIntegrationWithPromptAndProfileFixturesAndValidation(t *testing.T) {
|
|
||||||
root, err := filepath.Abs(filepath.Join("..", ".."))
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("failed to resolve repo root: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
promptsDir := filepath.Join(root, "examples", "prompts")
|
|
||||||
profilesDir := filepath.Join(root, "examples", "profiles")
|
|
||||||
schemasDir := filepath.Join(root, "examples", "schemas")
|
|
||||||
fixturesDir := filepath.Join(root, "examples", "fixtures")
|
|
||||||
t.Setenv("SCRIPTORIUM_API_KEY", "test-key")
|
|
||||||
|
|
||||||
runner := NewRunner(
|
|
||||||
promptdef.NewFilesystemRepository(promptsDir),
|
|
||||||
profile.NewFilesystemRepository(profilesDir),
|
|
||||||
artifact.NewCompositeReader(),
|
|
||||||
prompt.NewGoRenderer(),
|
|
||||||
&integrationLLM{},
|
|
||||||
validate.NewStandardValidator(schemasDir),
|
|
||||||
)
|
|
||||||
|
|
||||||
res, err := runner.Run(context.Background(), domain.RunRequest{
|
|
||||||
PromptID: "generic.structured_events",
|
|
||||||
Inputs: map[string]domain.ArtifactRef{
|
|
||||||
"transcript": {
|
|
||||||
Type: domain.ArtifactRefFile,
|
|
||||||
URI: filepath.Join(fixturesDir, "transcript.md"),
|
|
||||||
},
|
|
||||||
"glossary": {
|
|
||||||
Type: domain.ArtifactRefFile,
|
|
||||||
URI: filepath.Join(fixturesDir, "glossary.yml"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("expected no error, got %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
if res.PromptID != "generic.structured_events" {
|
|
||||||
t.Fatalf("unexpected prompt id: %q", res.PromptID)
|
|
||||||
}
|
|
||||||
if res.SelectedProfileID != "local-quality" {
|
|
||||||
t.Fatalf("expected selected profile local-quality from prompt default, got %q", res.SelectedProfileID)
|
|
||||||
}
|
|
||||||
if res.RunID == "" {
|
|
||||||
t.Fatal("expected run id")
|
|
||||||
}
|
|
||||||
if res.PromptHash == "" {
|
|
||||||
t.Fatal("expected prompt hash")
|
|
||||||
}
|
|
||||||
if res.PromptVersion != "1.0.0" {
|
|
||||||
t.Fatalf("unexpected prompt version: %q", res.PromptVersion)
|
|
||||||
}
|
|
||||||
if res.Validation.Status != domain.ValidationPassed {
|
|
||||||
t.Fatalf("expected passed validation, got %q", res.Validation.Status)
|
|
||||||
}
|
|
||||||
if res.Validation.Mode != domain.ValidationJSONSchema {
|
|
||||||
t.Fatalf("expected json_schema mode, got %q", res.Validation.Mode)
|
|
||||||
}
|
|
||||||
if lastIntegrationRequest.StructuredOutput == nil {
|
|
||||||
t.Fatal("expected provider-level structured output request for json_schema prompt")
|
|
||||||
}
|
|
||||||
if lastIntegrationRequest.StructuredOutput.Type != domain.StructuredOutputJSONSchema {
|
|
||||||
t.Fatalf("expected structured output type json_schema, got %q", lastIntegrationRequest.StructuredOutput.Type)
|
|
||||||
}
|
|
||||||
if lastIntegrationRequest.StructuredOutput.JSONSchema == nil || lastIntegrationRequest.StructuredOutput.JSONSchema.Schema == nil {
|
|
||||||
t.Fatalf("expected structured output json_schema payload, got %+v", lastIntegrationRequest.StructuredOutput.JSONSchema)
|
|
||||||
}
|
|
||||||
if res.Artifact.ContentType != "application/json" {
|
|
||||||
t.Fatalf("expected application/json output, got %q", res.Artifact.ContentType)
|
|
||||||
}
|
|
||||||
if len(res.RawOutput) == 0 {
|
|
||||||
t.Fatal("expected raw output to be preserved")
|
|
||||||
}
|
|
||||||
if res.PromptHash == "" {
|
|
||||||
t.Fatal("expected non-empty prompt hash")
|
|
||||||
}
|
|
||||||
if len(res.InputHashes) != 2 {
|
|
||||||
t.Fatalf("expected two input hashes, got %d", len(res.InputHashes))
|
|
||||||
}
|
|
||||||
if res.InputHashes["transcript"] == "" || res.InputHashes["glossary"] == "" {
|
|
||||||
t.Fatalf("expected both input hashes to be set, got %#v", res.InputHashes)
|
|
||||||
}
|
|
||||||
if res.Usage.TotalTokens != 78 {
|
|
||||||
t.Fatalf("expected usage from fake llm, got %+v", res.Usage)
|
|
||||||
}
|
|
||||||
if res.StartTime.IsZero() || res.EndTime.IsZero() {
|
|
||||||
t.Fatal("expected start/end timestamps")
|
|
||||||
}
|
|
||||||
if res.EndTime.Before(res.StartTime) {
|
|
||||||
t.Fatalf("expected end >= start, got start=%v end=%v", res.StartTime, res.EndTime)
|
|
||||||
}
|
|
||||||
if res.Duration < 0 {
|
|
||||||
t.Fatalf("expected non-negative duration, got %s", res.Duration)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
2
testdata/framework/fixtures/glossary.yml
vendored
Normal file
2
testdata/framework/fixtures/glossary.yml
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
archive: A catalogued collection of written records.
|
||||||
|
marker: A small label used to classify an entry.
|
||||||
2
testdata/framework/fixtures/transcript.md
vendored
Normal file
2
testdata/framework/fixtures/transcript.md
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
Nia labels the archive.
|
||||||
|
The archive receives a blue marker.
|
||||||
7
testdata/framework/profiles/contract-fast.yaml
vendored
Normal file
7
testdata/framework/profiles/contract-fast.yaml
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
id: contract-fast
|
||||||
|
endpoint: http://localhost:8000/v1
|
||||||
|
model: contract-fast-model
|
||||||
|
temperature: 0.2
|
||||||
|
max_tokens: 500
|
||||||
|
top_p: 1
|
||||||
|
timeout_seconds: 90
|
||||||
7
testdata/framework/profiles/contract-quality.yaml
vendored
Normal file
7
testdata/framework/profiles/contract-quality.yaml
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
id: contract-quality
|
||||||
|
endpoint: http://localhost:8000/v1
|
||||||
|
model: contract-quality-model
|
||||||
|
temperature: 0.1
|
||||||
|
max_tokens: 1000
|
||||||
|
top_p: 0.9
|
||||||
|
timeout_seconds: 120
|
||||||
1
testdata/framework/prompts/contract.markdown_summary.system.md
vendored
Normal file
1
testdata/framework/prompts/contract.markdown_summary.system.md
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
You summarize synthetic archive notes in clear Markdown.
|
||||||
7
testdata/framework/prompts/contract.markdown_summary.user.md
vendored
Normal file
7
testdata/framework/prompts/contract.markdown_summary.user.md
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
Summarize this transcript:
|
||||||
|
|
||||||
|
{{input "transcript"}}
|
||||||
|
|
||||||
|
Optional glossary:
|
||||||
|
|
||||||
|
{{input "glossary"}}
|
||||||
20
testdata/framework/prompts/contract.markdown_summary.yaml
vendored
Normal file
20
testdata/framework/prompts/contract.markdown_summary.yaml
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
id: contract.markdown_summary
|
||||||
|
version: "1.0.0"
|
||||||
|
default_profile: contract-fast
|
||||||
|
description: Summarize a synthetic transcript in Markdown.
|
||||||
|
inputs:
|
||||||
|
- name: transcript
|
||||||
|
required: true
|
||||||
|
content_type: text/markdown
|
||||||
|
- name: glossary
|
||||||
|
required: false
|
||||||
|
content_type: text/yaml
|
||||||
|
messages:
|
||||||
|
- role: system
|
||||||
|
content_file: ./contract.markdown_summary.system.md
|
||||||
|
- role: user
|
||||||
|
content_file: ./contract.markdown_summary.user.md
|
||||||
|
output:
|
||||||
|
format: markdown
|
||||||
|
validation_mode: basic
|
||||||
|
repair_attempts: 0
|
||||||
1
testdata/framework/prompts/contract.structured_events.system.md
vendored
Normal file
1
testdata/framework/prompts/contract.structured_events.system.md
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Return only JSON that satisfies the requested event schema.
|
||||||
7
testdata/framework/prompts/contract.structured_events.user.md
vendored
Normal file
7
testdata/framework/prompts/contract.structured_events.user.md
vendored
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
Extract events from this transcript:
|
||||||
|
|
||||||
|
{{input "transcript"}}
|
||||||
|
|
||||||
|
Optional glossary:
|
||||||
|
|
||||||
|
{{input "glossary"}}
|
||||||
21
testdata/framework/prompts/contract.structured_events.yaml
vendored
Normal file
21
testdata/framework/prompts/contract.structured_events.yaml
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
id: contract.structured_events
|
||||||
|
version: "1.0.0"
|
||||||
|
default_profile: contract-quality
|
||||||
|
description: Extract synthetic events as structured JSON.
|
||||||
|
inputs:
|
||||||
|
- name: transcript
|
||||||
|
required: true
|
||||||
|
content_type: text/markdown
|
||||||
|
- name: glossary
|
||||||
|
required: false
|
||||||
|
content_type: text/yaml
|
||||||
|
messages:
|
||||||
|
- role: system
|
||||||
|
content_file: ./contract.structured_events.system.md
|
||||||
|
- role: user
|
||||||
|
content_file: ./contract.structured_events.user.md
|
||||||
|
output:
|
||||||
|
format: json
|
||||||
|
validation_mode: json_schema
|
||||||
|
schema_path: structured_events.schema.json
|
||||||
|
repair_attempts: 0
|
||||||
19
testdata/framework/schemas/structured_events.schema.json
vendored
Normal file
19
testdata/framework/schemas/structured_events.schema.json
vendored
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||||
|
"type": "object",
|
||||||
|
"required": ["events"],
|
||||||
|
"properties": {
|
||||||
|
"events": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"required": ["title"],
|
||||||
|
"properties": {
|
||||||
|
"title": {"type": "string"}
|
||||||
|
},
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"additionalProperties": false
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user