feat(agentic): expose content schema generation on CLI

Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
Virgil 2026-04-02 05:39:01 +00:00
parent 1b986f9f2d
commit 52a431867a
2 changed files with 78 additions and 0 deletions

View file

@ -43,6 +43,8 @@ func (s *PrepSubsystem) registerCommands(ctx context.Context) {
c.Command("agentic:generate", core.Command{Description: "Generate content from a prompt using the platform content pipeline", Action: s.cmdGenerate})
c.Command("content/generate", core.Command{Description: "Generate content from a prompt using the platform content pipeline", Action: s.cmdGenerate})
c.Command("agentic:content/generate", core.Command{Description: "Generate content from a prompt using the platform content pipeline", Action: s.cmdGenerate})
c.Command("content/schema/generate", core.Command{Description: "Generate SEO schema JSON-LD for article, FAQ, or how-to content", Action: s.cmdContentSchemaGenerate})
c.Command("agentic:content/schema/generate", core.Command{Description: "Generate SEO schema JSON-LD for article, FAQ, or how-to content", Action: s.cmdContentSchemaGenerate})
c.Command("complete", core.Command{Description: "Run the completion pipeline (QA → PR → Verify → Commit → Ingest → Poke)", Action: s.cmdComplete})
c.Command("agentic:complete", core.Command{Description: "Run the completion pipeline (QA → PR → Verify → Commit → Ingest → Poke)", Action: s.cmdComplete})
c.Command("scan", core.Command{Description: "Scan Forge repos for actionable issues", Action: s.cmdScan})
@ -417,6 +419,45 @@ func (s *PrepSubsystem) cmdGenerate(options core.Options) core.Result {
return core.Result{OK: true}
}
func (s *PrepSubsystem) cmdContentSchemaGenerate(options core.Options) core.Result {
schemaType := optionStringValue(options, "schema_type", "schema-type", "type", "kind")
title := optionStringValue(options, "title", "headline")
if schemaType == "" || title == "" {
core.Print(nil, "usage: core-agent content schema generate --type=howto --title=\"Set up the workspace\" [--description=\"...\"] [--url=\"https://example.test/setup\"] [--author=\"Virgil\"] [--questions='[{\"question\":\"...\",\"answer\":\"...\"}]'] [--steps='[{\"name\":\"...\",\"text\":\"...\"}]']")
return core.Result{Value: core.E("agentic.cmdContentSchemaGenerate", "schema type and title are required", nil), OK: false}
}
result := s.handleContentSchemaGenerate(s.commandContext(), core.NewOptions(
core.Option{Key: "schema_type", Value: schemaType},
core.Option{Key: "title", Value: title},
core.Option{Key: "description", Value: optionStringValue(options, "description")},
core.Option{Key: "url", Value: optionStringValue(options, "url", "link")},
core.Option{Key: "author", Value: optionStringValue(options, "author")},
core.Option{Key: "published_at", Value: optionStringValue(options, "published_at", "published-at", "date_published")},
core.Option{Key: "modified_at", Value: optionStringValue(options, "modified_at", "modified-at", "date_modified")},
core.Option{Key: "language", Value: optionStringValue(options, "language", "in_language", "in-language")},
core.Option{Key: "image", Value: optionStringValue(options, "image", "image_url", "image-url")},
core.Option{Key: "questions", Value: optionAnyValue(options, "questions", "faq")},
core.Option{Key: "steps", Value: optionAnyValue(options, "steps")},
))
if !result.OK {
err := commandResultError("agentic.cmdContentSchemaGenerate", result)
core.Print(nil, "error: %v", err)
return core.Result{Value: err, OK: false}
}
output, ok := result.Value.(ContentSchemaOutput)
if !ok {
err := core.E("agentic.cmdContentSchemaGenerate", "invalid content schema output", nil)
core.Print(nil, "error: %v", err)
return core.Result{Value: err, OK: false}
}
core.Print(nil, "schema type: %s", output.SchemaType)
core.Print(nil, "schema json: %s", output.SchemaJSON)
return core.Result{Value: output, OK: true}
}
func (s *PrepSubsystem) cmdComplete(options core.Options) core.Result {
result := s.handleComplete(s.commandContext(), options)
if !result.OK {

View file

@ -1123,6 +1123,41 @@ func TestCommands_CmdGenerate_Good_BriefTemplate(t *testing.T) {
assert.Contains(t, output, "content: Template draft")
}
func TestCommands_CmdContentSchemaGenerate_Good(t *testing.T) {
s, _ := testPrepWithCore(t, nil)
output := captureStdout(t, func() {
r := s.cmdContentSchemaGenerate(core.NewOptions(
core.Option{Key: "type", Value: "howto"},
core.Option{Key: "title", Value: "Set up the workspace"},
core.Option{Key: "description", Value: "Prepare a fresh workspace for an agent."},
core.Option{Key: "url", Value: "https://example.test/workspace"},
core.Option{Key: "steps", Value: `[{"name":"Clone","text":"Clone the repository."},{"name":"Prepare","text":"Build the prompt."}]`},
))
assert.True(t, r.OK)
})
assert.Contains(t, output, "schema type: HowTo")
assert.Contains(t, output, `"@type":"HowTo"`)
assert.Contains(t, output, `"name":"Set up the workspace"`)
}
func TestCommands_CmdContentSchemaGenerate_Bad_MissingTitle(t *testing.T) {
s, _ := testPrepWithCore(t, nil)
r := s.cmdContentSchemaGenerate(core.NewOptions(
core.Option{Key: "type", Value: "howto"},
))
assert.False(t, r.OK)
}
func TestCommands_CmdContentSchemaGenerate_Ugly_InvalidSchemaType(t *testing.T) {
s, _ := testPrepWithCore(t, nil)
r := s.cmdContentSchemaGenerate(core.NewOptions(
core.Option{Key: "type", Value: "toast"},
core.Option{Key: "title", Value: "Set up the workspace"},
))
assert.False(t, r.OK)
}
func TestCommands_CmdComplete_Good(t *testing.T) {
s, c := testPrepWithCore(t, nil)
@ -1481,6 +1516,8 @@ func TestCommands_RegisterCommands_Good_AllRegistered(t *testing.T) {
assert.Contains(t, cmds, "agentic:resume")
assert.Contains(t, cmds, "content/generate")
assert.Contains(t, cmds, "agentic:content/generate")
assert.Contains(t, cmds, "content/schema/generate")
assert.Contains(t, cmds, "agentic:content/schema/generate")
assert.Contains(t, cmds, "complete")
assert.Contains(t, cmds, "agentic:complete")
assert.Contains(t, cmds, "scan")