@gobing-ai/knowledge-kit 0.0.6 → 0.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +21643 -11933
- package/package.json +4 -1
- package/plugins/generations/content-gen/package.json +2 -1
- package/plugins/generations/content-gen/src/index.ts +9 -8
- package/plugins/generations/content-gen/src/storm.ts +12 -4
- package/plugins/generations/voice-gen/package.json +17 -0
- package/plugins/generations/voice-gen/plugin.json +6 -0
- package/plugins/generations/voice-gen/src/concat.ts +218 -0
- package/plugins/generations/voice-gen/src/index.ts +213 -0
- package/plugins/generations/voice-gen/src/voicebox-client.ts +223 -0
- package/plugins/generations/voice-gen/src/voicescript.ts +365 -0
- package/plugins/generations/voice-gen/tsconfig.json +8 -0
- package/plugins/ingestions/karakeep-local/package.json +17 -0
- package/plugins/ingestions/karakeep-local/src/index.ts +31 -26
- package/plugins/ingestions/karakeep-local/tsconfig.json +4 -0
- package/plugins/ingestions/web-search/package.json +4 -1
- package/plugins/ingestions/web-search/src/index.ts +299 -17
- package/plugins/kk/README.md +12 -1
- package/plugins/kk/commands/workflow-run.md +202 -0
- package/plugins/kk/config.example.yaml +34 -0
- package/plugins/kk/scripts/render-md.ts +150 -0
- package/plugins/kk/skills/{kk-judge → content-judge}/SKILL.md +13 -14
- package/plugins/kk/skills/{kk-judge → content-judge}/references/rubrics.md +2 -2
- package/plugins/kk/skills/{kk-judge → content-judge}/references/workflow-integration.md +17 -15
- package/plugins/kk/skills/itc-generating/SKILL.md +147 -0
- package/plugins/kk/skills/itc-generating/references/generic-craft.md +80 -0
- package/plugins/kk/skills/itc-generating/references/platform-english.md +72 -0
- package/plugins/kk/skills/itc-generating/references/platform-wechat.md +60 -0
- package/plugins/kk/skills/itc-generating/references/skill-authoring.md +62 -0
- package/plugins/kk/skills/storm-research/SKILL.md +173 -0
- package/plugins/kk/skills/{kk-topic → topic}/SKILL.md +4 -4
- package/plugins/kk/workflows/judge-gated-publish-example.yaml +101 -0
- package/plugins/kk/workflows/kk-ingest-generate-publish.yaml +72 -0
- package/plugins/kk/workflows/kk-itc.yaml +285 -0
- package/plugins/kk/workflows/kk-solo-podcast.yaml +374 -0
- package/plugins/kk/workflows/kk-storm-research.yaml +184 -0
- package/plugins/kk/workflows/validate-voicescript.ts +226 -0
- package/plugins/publishings/emdash-pub/package.json +17 -0
- package/plugins/publishings/emdash-pub/plugin.json +7 -0
- package/plugins/publishings/emdash-pub/src/index.ts +450 -0
- package/plugins/publishings/emdash-pub/tsconfig.json +4 -0
- package/plugins/publishings/qiita-pub/package.json +2 -1
- package/plugins/publishings/qiita-pub/src/index.ts +9 -9
- package/plugins/publishings/surfdash-pub/package.json +2 -1
- package/plugins/publishings/surfdash-pub/src/index.ts +16 -11
- package/plugins/publishings/zenn-pub/package.json +2 -1
- package/plugins/publishings/zenn-pub/src/index.ts +11 -11
- package/plugins/kk/agents/kk-judge-compliance.md +0 -37
- package/plugins/kk/agents/kk-judge-tech.md +0 -35
- package/plugins/kk/agents/kk-judge-tone.md +0 -37
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"$schema": "@gobing-ai/spur/schemas/state-machine-workflow.schema.json"
|
|
2
|
+
kind: state-machine
|
|
3
|
+
name: judge-gated-publish
|
|
4
|
+
description: "Example workflow where an LLM-as-judge agent.run step gates a publish transition"
|
|
5
|
+
initialState: generate
|
|
6
|
+
terminalStates:
|
|
7
|
+
- done
|
|
8
|
+
- failed
|
|
9
|
+
failureStates:
|
|
10
|
+
- failed
|
|
11
|
+
vars:
|
|
12
|
+
contentFile: ".spur/run/content.json"
|
|
13
|
+
verdictFile: ".spur/run/verdict.json"
|
|
14
|
+
rubric: "general"
|
|
15
|
+
maxRetries: "2"
|
|
16
|
+
# attempt is mutated by the revise loop; initialize to 0.
|
|
17
|
+
attempt: "0"
|
|
18
|
+
spurBin: "spur"
|
|
19
|
+
states:
|
|
20
|
+
- id: generate
|
|
21
|
+
description: "Generate content from brief or docs (kk invoke <generator>)"
|
|
22
|
+
onEnter:
|
|
23
|
+
- kind: shell
|
|
24
|
+
options:
|
|
25
|
+
# Seed the verdict so the judge gate guards can be evaluated in --dry-run
|
|
26
|
+
# (dry-run skips actions but still evaluates shell guards). A real run's
|
|
27
|
+
# judge step overwrites this file before the gate is read.
|
|
28
|
+
command: "echo '{\"verdict\":\"PASS\",\"score\":0.0}' > ${vars.verdictFile} && echo 'generating content...'"
|
|
29
|
+
- id: judge
|
|
30
|
+
description: "Evaluate generated content via the judge skill (agent.run)"
|
|
31
|
+
onEnter:
|
|
32
|
+
# `agent.run` is registered by the kk workflow host: it spawns an agent that loads the
|
|
33
|
+
# content-judge skill, evaluates the content against ${vars.rubric}, and writes the verdict
|
|
34
|
+
# JSON to ${vars.verdictFile}. Under `spur workflow run` (dry-run), this action is
|
|
35
|
+
# skipped — the seeded verdict above keeps the gate evaluable. See
|
|
36
|
+
# plugins/kk/skills/content-judge/SKILL.md and references/workflow-integration.md.
|
|
37
|
+
- kind: agent.run
|
|
38
|
+
options:
|
|
39
|
+
role: reviewer
|
|
40
|
+
input: |
|
|
41
|
+
Evaluate the content at ${vars.contentFile} against the ${vars.rubric} rubric.
|
|
42
|
+
Load plugins/kk/skills/content-judge/SKILL.md and its references/rubrics.md.
|
|
43
|
+
Write the verdict JSON to ${vars.verdictFile} per the contract in SKILL.md.
|
|
44
|
+
Print the verdict path as the last line of stdout.
|
|
45
|
+
expectFile: ${vars.verdictFile}
|
|
46
|
+
- id: publish
|
|
47
|
+
description: "Publish content after clearing judge gate (kk fanout)"
|
|
48
|
+
onEnter:
|
|
49
|
+
- kind: shell
|
|
50
|
+
options:
|
|
51
|
+
command: "echo 'publishing content...'"
|
|
52
|
+
- id: done
|
|
53
|
+
description: "Publish completed successfully"
|
|
54
|
+
- id: failed
|
|
55
|
+
description: "Judge rejected content (FAIL) or retries exhausted (NEEDS_REVISION)"
|
|
56
|
+
|
|
57
|
+
transitions:
|
|
58
|
+
- from: generate
|
|
59
|
+
to: judge
|
|
60
|
+
description: "Content generated -> proceed to evaluation"
|
|
61
|
+
guard:
|
|
62
|
+
kind: always
|
|
63
|
+
|
|
64
|
+
# PASS -> publish.
|
|
65
|
+
- from: judge
|
|
66
|
+
to: publish
|
|
67
|
+
description: "Judge verdict is PASS (or file absent under --dry-run) -> proceed to publish"
|
|
68
|
+
guard:
|
|
69
|
+
kind: shell
|
|
70
|
+
options:
|
|
71
|
+
# Fail-closed on an explicit non-PASS verdict; fail-open only when the file is
|
|
72
|
+
# absent, which happens under --dry-run (actions are skipped, so the judge
|
|
73
|
+
# never writes its verdict). A real run always has the file.
|
|
74
|
+
command: 'v="$(jq -r .verdict ${vars.verdictFile} 2>/dev/null)"; test -z "$v" -o "$v" = PASS'
|
|
75
|
+
|
|
76
|
+
# NEEDS_REVISION -> back to generate with a bounded retry budget.
|
|
77
|
+
- from: judge
|
|
78
|
+
to: generate
|
|
79
|
+
description: "Judge verdict is NEEDS_REVISION and retry budget remains -> regenerate with feedback"
|
|
80
|
+
guard:
|
|
81
|
+
kind: shell
|
|
82
|
+
options:
|
|
83
|
+
# Allow the revise loop only while the attempt counter is below maxRetries.
|
|
84
|
+
# The shell kind cannot mutate vars, so the host (or a sidecar note action) is
|
|
85
|
+
# responsible for incrementing attempt on each loop in a real run.
|
|
86
|
+
command: 'v="$(jq -r .verdict ${vars.verdictFile} 2>/dev/null)"; test "$v" = NEEDS_REVISION -a "$attempt" -lt "$maxRetries"'
|
|
87
|
+
|
|
88
|
+
# FAIL, or NEEDS_REVISION with no retries left -> failed.
|
|
89
|
+
- from: judge
|
|
90
|
+
to: failed
|
|
91
|
+
description: "Judge verdict is FAIL, or NEEDS_REVISION with retries exhausted -> block publish"
|
|
92
|
+
guard:
|
|
93
|
+
kind: shell
|
|
94
|
+
options:
|
|
95
|
+
command: 'v="$(jq -r .verdict ${vars.verdictFile} 2>/dev/null)"; test -n "$v" && { test "$v" = FAIL || test "$v" = NEEDS_REVISION -a "$attempt" -ge "$maxRetries"; }'
|
|
96
|
+
|
|
97
|
+
- from: publish
|
|
98
|
+
to: done
|
|
99
|
+
description: "Publish done"
|
|
100
|
+
guard:
|
|
101
|
+
kind: always
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Linear state-machine workflow template for knowledge-kit plugin platform:
|
|
2
|
+
# ingest -> generate -> publish -> done.
|
|
3
|
+
"$schema": "@gobing-ai/spur/schemas/state-machine-workflow.schema.json"
|
|
4
|
+
name: kk-ingest-generate-publish
|
|
5
|
+
kind: state-machine
|
|
6
|
+
description: Chained ingestion, generator, and publish plugins via kk executor run
|
|
7
|
+
initialState: ingest
|
|
8
|
+
terminalStates:
|
|
9
|
+
- done
|
|
10
|
+
- failed
|
|
11
|
+
vars:
|
|
12
|
+
ingestion_plugin: "karakeep-local"
|
|
13
|
+
generator_plugin: "content-gen"
|
|
14
|
+
publish_plugin: "surfdash-pub"
|
|
15
|
+
source: "./source"
|
|
16
|
+
work_dir: "./work"
|
|
17
|
+
plugins_path: "./plugins"
|
|
18
|
+
|
|
19
|
+
states:
|
|
20
|
+
- id: ingest
|
|
21
|
+
description: Run ingestion plugin to produce document list (docs.json)
|
|
22
|
+
onEnter:
|
|
23
|
+
- kind: shell
|
|
24
|
+
options:
|
|
25
|
+
command: kk executor run ${vars.ingestion_plugin} --in ${vars.source} --out ${vars.work_dir}/docs.json --plugins-path ${vars.plugins_path}
|
|
26
|
+
|
|
27
|
+
- id: generate
|
|
28
|
+
description: Run content generator plugin to produce markdown content (content.json)
|
|
29
|
+
onEnter:
|
|
30
|
+
- kind: shell
|
|
31
|
+
options:
|
|
32
|
+
command: kk executor run ${vars.generator_plugin} --in ${vars.work_dir}/docs.json --out ${vars.work_dir}/content.json --plugins-path ${vars.plugins_path}
|
|
33
|
+
|
|
34
|
+
- id: publish
|
|
35
|
+
description: Run publish plugin to deploy content and receive result (result.json)
|
|
36
|
+
onEnter:
|
|
37
|
+
- kind: shell
|
|
38
|
+
options:
|
|
39
|
+
command: kk executor run ${vars.publish_plugin} --in ${vars.work_dir}/content.json --out ${vars.work_dir}/result.json --plugins-path ${vars.plugins_path}
|
|
40
|
+
|
|
41
|
+
- id: done
|
|
42
|
+
description: Terminal — all three plugin steps succeeded
|
|
43
|
+
- id: failed
|
|
44
|
+
description: Terminal — one of the plugin run steps failed
|
|
45
|
+
|
|
46
|
+
transitions:
|
|
47
|
+
- from: ingest
|
|
48
|
+
to: generate
|
|
49
|
+
description: Ingest succeeded — proceed to content generation
|
|
50
|
+
guard:
|
|
51
|
+
kind: action-ok
|
|
52
|
+
- from: ingest
|
|
53
|
+
to: failed
|
|
54
|
+
description: Ingest failed — terminate workflow
|
|
55
|
+
|
|
56
|
+
- from: generate
|
|
57
|
+
to: publish
|
|
58
|
+
description: Content generation succeeded — proceed to publish
|
|
59
|
+
guard:
|
|
60
|
+
kind: action-ok
|
|
61
|
+
- from: generate
|
|
62
|
+
to: failed
|
|
63
|
+
description: Generator failed — terminate workflow
|
|
64
|
+
|
|
65
|
+
- from: publish
|
|
66
|
+
to: done
|
|
67
|
+
description: Publish succeeded — workflow complete
|
|
68
|
+
guard:
|
|
69
|
+
kind: action-ok
|
|
70
|
+
- from: publish
|
|
71
|
+
to: failed
|
|
72
|
+
description: Publish failed — terminate workflow
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
---
|
|
2
|
+
"$schema": "@gobing-ai/spur/schemas/state-machine-workflow.schema.json"
|
|
3
|
+
name: kk-itc
|
|
4
|
+
kind: state-machine
|
|
5
|
+
description: >-
|
|
6
|
+
IT content authoring pipeline using topic/itc-generating, Spur HITL gates, and optional judging
|
|
7
|
+
initialState: prepare
|
|
8
|
+
terminalStates:
|
|
9
|
+
- done
|
|
10
|
+
- failed
|
|
11
|
+
failureStates:
|
|
12
|
+
- failed
|
|
13
|
+
|
|
14
|
+
vars:
|
|
15
|
+
topic: ""
|
|
16
|
+
input_file: ""
|
|
17
|
+
work_dir: ""
|
|
18
|
+
writer: "itc-generating"
|
|
19
|
+
playbook: "generic"
|
|
20
|
+
research: "false"
|
|
21
|
+
judge: "false"
|
|
22
|
+
outline: ""
|
|
23
|
+
force: "false"
|
|
24
|
+
rubric: "tech-accuracy"
|
|
25
|
+
verdictFile: ".spur/run/${vars.__runId}-itc-verdict.json"
|
|
26
|
+
agent: ""
|
|
27
|
+
__runId: "itc"
|
|
28
|
+
__hitlAnswer: ""
|
|
29
|
+
__hitlInput: ""
|
|
30
|
+
|
|
31
|
+
states:
|
|
32
|
+
- id: prepare
|
|
33
|
+
description: "mkdir work_dir, 2-outline, 3-draft; validate XOR topic/input_file; write brief.md"
|
|
34
|
+
onEnter:
|
|
35
|
+
- kind: shell
|
|
36
|
+
options:
|
|
37
|
+
command: >-
|
|
38
|
+
set -e;
|
|
39
|
+
if [ -z "${vars.work_dir}" ]; then
|
|
40
|
+
echo "missing work_dir" >&2; exit 1;
|
|
41
|
+
fi;
|
|
42
|
+
mkdir -p "${vars.work_dir}" "${vars.work_dir}/2-outline" "${vars.work_dir}/3-draft";
|
|
43
|
+
if [ -n "${vars.topic}" ] && [ -n "${vars.input_file}" ]; then
|
|
44
|
+
echo "XOR violation: both topic and input_file set" >&2; exit 1;
|
|
45
|
+
fi;
|
|
46
|
+
if [ -z "${vars.topic}" ] && [ -z "${vars.input_file}" ]; then
|
|
47
|
+
echo "XOR violation: neither topic nor input_file set" >&2; exit 1;
|
|
48
|
+
fi;
|
|
49
|
+
if [ -f "${vars.work_dir}/brief.md" ] && [ "${vars.force}" != "true" ]; then
|
|
50
|
+
echo "initialization target already exists at ${vars.work_dir}/brief.md; pass force=true to replace" >&2; exit 1;
|
|
51
|
+
fi;
|
|
52
|
+
if [ -n "${vars.topic}" ]; then
|
|
53
|
+
printf '%s\n' "${vars.topic}" > "${vars.work_dir}/brief.md";
|
|
54
|
+
else
|
|
55
|
+
if [ ! -f "${vars.input_file}" ]; then
|
|
56
|
+
echo "input file not found: ${vars.input_file}" >&2; exit 1;
|
|
57
|
+
fi;
|
|
58
|
+
cp "${vars.input_file}" "${vars.work_dir}/brief.md";
|
|
59
|
+
fi;
|
|
60
|
+
|
|
61
|
+
- id: research
|
|
62
|
+
description: "Conduct preliminary topic research via storm-research (agent.run)"
|
|
63
|
+
onEnter:
|
|
64
|
+
- kind: agent.run
|
|
65
|
+
options:
|
|
66
|
+
role: scribe
|
|
67
|
+
agent: ${vars.agent}
|
|
68
|
+
input: |
|
|
69
|
+
Load plugins/kk/skills/storm-research/SKILL.md.
|
|
70
|
+
Run storm-research on the topic or input file specified in the brief at ${vars.work_dir}/brief.md.
|
|
71
|
+
|
|
72
|
+
- id: outline-write
|
|
73
|
+
description: "Generate outline options a, b (and optional c) via writer skill (agent.run)"
|
|
74
|
+
onEnter:
|
|
75
|
+
- kind: agent.run
|
|
76
|
+
options:
|
|
77
|
+
role: scribe
|
|
78
|
+
agent: ${vars.agent}
|
|
79
|
+
input: |
|
|
80
|
+
Load plugins/kk/skills/${vars.writer}/SKILL.md.
|
|
81
|
+
Generate outline options (outline-option-a.md, outline-option-b.md, and optionally outline-option-c.md) in ${vars.work_dir}/2-outline/ from the brief at ${vars.work_dir}/brief.md using playbook ${vars.playbook}.
|
|
82
|
+
Do not wait for operator selection; write the option files.
|
|
83
|
+
expectFile: ${vars.work_dir}/2-outline/outline-option-a.md
|
|
84
|
+
- kind: shell
|
|
85
|
+
options:
|
|
86
|
+
command: >-
|
|
87
|
+
test -f "${vars.work_dir}/2-outline/outline-option-b.md" || { echo "missing required outline-option-b.md" >&2; exit 1; }
|
|
88
|
+
|
|
89
|
+
- id: outline-select
|
|
90
|
+
description: "Operator selects preferred outline option"
|
|
91
|
+
pause: true
|
|
92
|
+
onEnter:
|
|
93
|
+
- kind: hitl.select
|
|
94
|
+
options:
|
|
95
|
+
prompt: "Select an approved outline option from ${vars.work_dir}/2-outline/ (outline-option-a.md, outline-option-b.md, or outline-option-c.md):"
|
|
96
|
+
options:
|
|
97
|
+
- a
|
|
98
|
+
- b
|
|
99
|
+
- c
|
|
100
|
+
var: __hitlAnswer
|
|
101
|
+
|
|
102
|
+
- id: outline-commit
|
|
103
|
+
description: "Copy selected outline to outline-approved.md"
|
|
104
|
+
onEnter:
|
|
105
|
+
- kind: shell
|
|
106
|
+
options:
|
|
107
|
+
command: >-
|
|
108
|
+
sel="${vars.outline}";
|
|
109
|
+
if [ -z "$sel" ]; then sel="${vars.__hitlAnswer}"; fi;
|
|
110
|
+
if [ -z "$sel" ]; then sel="a"; fi;
|
|
111
|
+
src="${vars.work_dir}/2-outline/outline-option-$sel.md";
|
|
112
|
+
if [ ! -f "$src" ]; then
|
|
113
|
+
echo "selected outline file not found: $src" >&2; exit 1;
|
|
114
|
+
fi;
|
|
115
|
+
cp "$src" "${vars.work_dir}/2-outline/outline-approved.md";
|
|
116
|
+
|
|
117
|
+
- id: draft-write
|
|
118
|
+
description: "Author full technical draft from approved outline (agent.run)"
|
|
119
|
+
onEnter:
|
|
120
|
+
- kind: agent.run
|
|
121
|
+
options:
|
|
122
|
+
role: scribe
|
|
123
|
+
agent: ${vars.agent}
|
|
124
|
+
input: |
|
|
125
|
+
Load plugins/kk/skills/${vars.writer}/SKILL.md.
|
|
126
|
+
Author the technical draft at ${vars.work_dir}/3-draft/draft-article.md based on approved outline ${vars.work_dir}/2-outline/outline-approved.md and brief ${vars.work_dir}/brief.md using playbook ${vars.playbook}.
|
|
127
|
+
Revision feedback: ${vars.__hitlInput}
|
|
128
|
+
expectFile: ${vars.work_dir}/3-draft/draft-article.md
|
|
129
|
+
|
|
130
|
+
- id: draft-review
|
|
131
|
+
description: "Operator reviews and approves or requests revision on draft-article.md"
|
|
132
|
+
pause: true
|
|
133
|
+
onEnter:
|
|
134
|
+
- kind: hitl.confirm
|
|
135
|
+
options:
|
|
136
|
+
prompt: "Review draft at ${vars.work_dir}/3-draft/draft-article.md. Approve?"
|
|
137
|
+
var: __hitlAnswer
|
|
138
|
+
|
|
139
|
+
- id: draft-revise
|
|
140
|
+
description: "Collect revision feedback from operator (bounded by 3 rounds)"
|
|
141
|
+
pause: true
|
|
142
|
+
onEnter:
|
|
143
|
+
- kind: shell
|
|
144
|
+
options:
|
|
145
|
+
command: >-
|
|
146
|
+
mkdir -p .spur/run;
|
|
147
|
+
run_id="${vars.__runId}";
|
|
148
|
+
if [ -z "$run_id" ]; then run_id="itc"; fi;
|
|
149
|
+
count_file=".spur/run/$run_id-itc-revise-count";
|
|
150
|
+
curr=$(cat "$count_file" 2>/dev/null || echo 0);
|
|
151
|
+
echo $((curr + 1)) > "$count_file";
|
|
152
|
+
- kind: hitl.input
|
|
153
|
+
options:
|
|
154
|
+
prompt: "Provide specific revision feedback for ${vars.work_dir}/3-draft/draft-article.md:"
|
|
155
|
+
var: __hitlInput
|
|
156
|
+
|
|
157
|
+
- id: judge
|
|
158
|
+
description: "Evaluate technical draft with content-judge (agent.run)"
|
|
159
|
+
onEnter:
|
|
160
|
+
- kind: agent.run
|
|
161
|
+
options:
|
|
162
|
+
role: reviewer
|
|
163
|
+
agent: ${vars.agent}
|
|
164
|
+
input: |
|
|
165
|
+
Load plugins/kk/skills/content-judge/SKILL.md and its references/rubrics.md.
|
|
166
|
+
Evaluate the draft at ${vars.work_dir}/3-draft/draft-article.md against the ${vars.rubric} rubric.
|
|
167
|
+
Write the verdict JSON to ${vars.verdictFile} per the contract in SKILL.md.
|
|
168
|
+
Print the verdict path as the last line of stdout.
|
|
169
|
+
expectFile: ${vars.verdictFile}
|
|
170
|
+
|
|
171
|
+
- id: done
|
|
172
|
+
description: "Terminal — IT content draft generated and approved successfully"
|
|
173
|
+
- id: failed
|
|
174
|
+
description: "Terminal — IT content workflow failed or rejected"
|
|
175
|
+
|
|
176
|
+
transitions:
|
|
177
|
+
- from: prepare
|
|
178
|
+
to: research
|
|
179
|
+
description: "Research enabled -> proceed to storm-research"
|
|
180
|
+
guard:
|
|
181
|
+
kind: shell
|
|
182
|
+
options:
|
|
183
|
+
command: 'test "${vars.research}" = "true"'
|
|
184
|
+
|
|
185
|
+
- from: prepare
|
|
186
|
+
to: outline-write
|
|
187
|
+
description: "Research disabled -> proceed directly to outline generation"
|
|
188
|
+
guard:
|
|
189
|
+
kind: shell
|
|
190
|
+
options:
|
|
191
|
+
command: 'test "${vars.research}" != "true"'
|
|
192
|
+
|
|
193
|
+
- from: research
|
|
194
|
+
to: outline-write
|
|
195
|
+
description: "Research completed -> proceed to outline generation"
|
|
196
|
+
guard:
|
|
197
|
+
kind: always
|
|
198
|
+
|
|
199
|
+
- from: outline-write
|
|
200
|
+
to: outline-select
|
|
201
|
+
description: "Outline not pre-selected -> pause for operator selection"
|
|
202
|
+
guard:
|
|
203
|
+
kind: shell
|
|
204
|
+
options:
|
|
205
|
+
command: 'test -z "${vars.outline}"'
|
|
206
|
+
|
|
207
|
+
- from: outline-write
|
|
208
|
+
to: outline-commit
|
|
209
|
+
description: "Outline pre-selected -> skip interactive selection"
|
|
210
|
+
guard:
|
|
211
|
+
kind: shell
|
|
212
|
+
options:
|
|
213
|
+
command: 'test -n "${vars.outline}"'
|
|
214
|
+
|
|
215
|
+
- from: outline-select
|
|
216
|
+
to: outline-commit
|
|
217
|
+
description: "Outline selected -> commit approved outline"
|
|
218
|
+
guard:
|
|
219
|
+
kind: always
|
|
220
|
+
|
|
221
|
+
- from: outline-commit
|
|
222
|
+
to: draft-write
|
|
223
|
+
description: "Approved outline committed -> write draft"
|
|
224
|
+
guard:
|
|
225
|
+
kind: always
|
|
226
|
+
|
|
227
|
+
- from: draft-write
|
|
228
|
+
to: draft-review
|
|
229
|
+
description: "Draft written -> pause for operator review"
|
|
230
|
+
guard:
|
|
231
|
+
kind: always
|
|
232
|
+
|
|
233
|
+
- from: draft-review
|
|
234
|
+
to: judge
|
|
235
|
+
description: "Draft approved and judge enabled -> evaluate quality"
|
|
236
|
+
guard:
|
|
237
|
+
kind: shell
|
|
238
|
+
options:
|
|
239
|
+
command: '{ test -z "${vars.__hitlAnswer}" || test "${vars.__hitlAnswer}" = "yes"; } && test "${vars.judge}" = "true"'
|
|
240
|
+
|
|
241
|
+
- from: draft-review
|
|
242
|
+
to: done
|
|
243
|
+
description: "Draft approved and judge disabled -> complete workflow"
|
|
244
|
+
guard:
|
|
245
|
+
kind: shell
|
|
246
|
+
options:
|
|
247
|
+
command: '{ test -z "${vars.__hitlAnswer}" || test "${vars.__hitlAnswer}" = "yes"; } && test "${vars.judge}" != "true"'
|
|
248
|
+
|
|
249
|
+
- from: draft-review
|
|
250
|
+
to: draft-revise
|
|
251
|
+
description: "Draft rejected with revision budget remaining -> collect feedback"
|
|
252
|
+
guard:
|
|
253
|
+
kind: shell
|
|
254
|
+
options:
|
|
255
|
+
command: 'test "${vars.__hitlAnswer}" = "no" && { run_id="${vars.__runId}"; if [ -z "$run_id" ]; then run_id="itc"; fi; test "$(cat .spur/run/$run_id-itc-revise-count 2>/dev/null || echo 0)" -lt 3; }'
|
|
256
|
+
|
|
257
|
+
- from: draft-review
|
|
258
|
+
to: failed
|
|
259
|
+
description: "Draft rejected with revision budget exhausted -> fail"
|
|
260
|
+
guard:
|
|
261
|
+
kind: shell
|
|
262
|
+
options:
|
|
263
|
+
command: 'test "${vars.__hitlAnswer}" = "no" && { run_id="${vars.__runId}"; if [ -z "$run_id" ]; then run_id="itc"; fi; test "$(cat .spur/run/$run_id-itc-revise-count 2>/dev/null || echo 0)" -ge 3; }'
|
|
264
|
+
|
|
265
|
+
- from: draft-revise
|
|
266
|
+
to: draft-write
|
|
267
|
+
description: "Feedback collected -> rewrite draft"
|
|
268
|
+
guard:
|
|
269
|
+
kind: always
|
|
270
|
+
|
|
271
|
+
- from: judge
|
|
272
|
+
to: done
|
|
273
|
+
description: "Judge verdict is PASS (or empty in dry-run) -> complete workflow"
|
|
274
|
+
guard:
|
|
275
|
+
kind: shell
|
|
276
|
+
options:
|
|
277
|
+
command: 'v="$(jq -r .verdict ${vars.verdictFile} 2>/dev/null)"; test -z "$v" -o "$v" = PASS'
|
|
278
|
+
|
|
279
|
+
- from: judge
|
|
280
|
+
to: failed
|
|
281
|
+
description: "Judge verdict is not PASS -> fail"
|
|
282
|
+
guard:
|
|
283
|
+
kind: shell
|
|
284
|
+
options:
|
|
285
|
+
command: 'v="$(jq -r .verdict ${vars.verdictFile} 2>/dev/null)"; test -n "$v" -a "$v" != PASS'
|