Add Tomorrow generated text contract

This commit is contained in:
2026-06-14 23:25:55 +00:00
parent 386263784c
commit 120bce3391
8 changed files with 340 additions and 17 deletions

View File

@@ -0,0 +1,18 @@
# Tomorrow Generated Text
Create structured prose for the Tomorrow Report using the supplied
weatherreporter data package.
Return JSON that matches the Scriptorium-registered schema for
`weather.tomorrow_generated_text`.
Fields:
- `summary`: concise overview of tomorrow's weather.
- `forecast_discussion`: one or more paragraph strings explaining the main
weather drivers and forecast reasoning.
- `precipitation_timing`: optional plain-language precipitation timing context.
- `confidence`: optional uncertainty or confidence note.
Use deterministic facts from the data package for weather details. Do not
invent watches, warnings, precipitation windows, temperatures, or timing.

View File

@@ -16,7 +16,8 @@ var templates = map[string]string{
}
var schemas = map[string]string{
"hourly": "schemas/hourly.generated_text.schema.json",
"hourly": "schemas/hourly.generated_text.schema.json",
"tomorrow": "schemas/tomorrow.generated_text.schema.json",
}
func Template(id string) (string, error) {

View File

@@ -23,6 +23,61 @@ func TestSchemaLookup(t *testing.T) {
if err != nil {
t.Fatalf("Schema() error = %v", err)
}
assertStringSchema(t, data, "summary,forecast_discussion", []string{"summary", "forecast_discussion", "precipitation_timing", "confidence"})
}
func TestTomorrowSchemaLookup(t *testing.T) {
data, err := Schema("tomorrow")
if err != nil {
t.Fatalf("Schema() error = %v", err)
}
schema := assertSchema(t, data, "summary,forecast_discussion")
property, ok := schema.Properties["forecast_discussion"].(map[string]any)
if !ok {
t.Fatal("schema property forecast_discussion missing or invalid")
}
if property["type"] != "array" {
t.Fatalf("forecast_discussion type = %v, want array", property["type"])
}
if property["minItems"] != float64(1) {
t.Fatalf("forecast_discussion minItems = %v, want 1", property["minItems"])
}
items, ok := property["items"].(map[string]any)
if !ok || items["type"] != "string" {
t.Fatalf("forecast_discussion items = %#v, want string items", property["items"])
}
for _, field := range []string{"summary", "precipitation_timing", "confidence"} {
property, ok := schema.Properties[field].(map[string]any)
if !ok {
t.Fatalf("schema property %q missing or invalid", field)
}
if property["type"] != "string" {
t.Fatalf("schema property %q type = %v, want string", field, property["type"])
}
}
}
func assertStringSchema(t *testing.T, data []byte, required string, fields []string) {
t.Helper()
schema := assertSchema(t, data, required)
for _, field := range fields {
property, ok := schema.Properties[field].(map[string]any)
if !ok {
t.Fatalf("schema property %q missing or invalid", field)
}
if property["type"] != "string" {
t.Fatalf("schema property %q type = %v, want string", field, property["type"])
}
}
}
func assertSchema(t *testing.T, data []byte, required string) struct {
Type string `json:"type"`
AdditionalProperties bool `json:"additionalProperties"`
Required []string `json:"required"`
Properties map[string]any `json:"properties"`
} {
t.Helper()
var schema struct {
Type string `json:"type"`
AdditionalProperties bool `json:"additionalProperties"`
@@ -38,18 +93,10 @@ func TestSchemaLookup(t *testing.T) {
if schema.AdditionalProperties {
t.Fatal("additionalProperties = true, want false")
}
if strings.Join(schema.Required, ",") != "summary,forecast_discussion" {
t.Fatalf("required = %#v, want summary/forecast_discussion", schema.Required)
}
for _, field := range []string{"summary", "forecast_discussion", "precipitation_timing", "confidence"} {
property, ok := schema.Properties[field].(map[string]any)
if !ok {
t.Fatalf("schema property %q missing or invalid", field)
}
if property["type"] != "string" {
t.Fatalf("schema property %q type = %v, want string", field, property["type"])
}
if strings.Join(schema.Required, ",") != required {
t.Fatalf("required = %#v, want %s", schema.Required, required)
}
return schema
}
func TestRenderHourly(t *testing.T) {

View File

@@ -0,0 +1,29 @@
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "weatherreporter.tomorrow.generated_text.schema.json",
"title": "Tomorrow GeneratedText",
"type": "object",
"additionalProperties": false,
"required": [
"summary",
"forecast_discussion"
],
"properties": {
"summary": {
"type": "string"
},
"forecast_discussion": {
"type": "array",
"items": {
"type": "string"
},
"minItems": 1
},
"precipitation_timing": {
"type": "string"
},
"confidence": {
"type": "string"
}
}
}