@gobing-ai/knowledge-kit 0.0.36 → 0.1.0
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/.claude-plugin/marketplace.json +1 -1
- package/dist/board/collect/index.css +654 -16
- package/dist/board/collect/index.js +191 -64
- package/dist/board/daily-voice/index.css +679 -12
- package/dist/board/daily-voice/index.js +185 -66
- package/dist/board/itc/index.css +679 -13
- package/dist/board/itc/index.js +188 -66
- package/dist/index.js +2878 -152
- package/package.json +3 -2
- package/plugins/generations/content-gen/dist/index.js +158 -12
- package/plugins/generations/core-facts-gen/dist/index.js +158 -12
- package/plugins/generations/daily-article-gen/dist/index.js +158 -12
- package/plugins/generations/dailynews-gen/dist/index.js +180 -12
- package/plugins/generations/dailynews-gen/src/script-plan.ts +32 -0
- package/plugins/generations/episode-plan-gen/dist/index.js +158 -12
- package/plugins/generations/gemini-tts/README.md +4 -3
- package/plugins/generations/gemini-tts/dist/index.js +158 -12
- package/plugins/generations/image-gen/dist/index.js +158 -12
- package/plugins/generations/news-report-gen/dist/index.js +158 -12
- package/plugins/generations/omni-voice-gen/README.md +15 -4
- package/plugins/generations/omni-voice-gen/profiles.json +1 -2
- package/plugins/generations/voice-gen/dist/index.js +158 -12
- package/plugins/generations/voxcpm-tts/README.md +21 -1
- package/plugins/generations/voxcpm-tts/dist/index.js +173 -13
- package/plugins/generations/voxcpm-tts/scripts/audit-speaker-consistency.py +109 -0
- package/plugins/generations/voxcpm-tts/src/voxcpm-client.ts +28 -1
- package/plugins/ingestions/aihot-ingest/dist/index.js +158 -12
- package/plugins/ingestions/horizon-ingest/dist/index.js +158 -12
- package/plugins/ingestions/last30days-ingest/dist/index.js +158 -12
- package/plugins/ingestions/web-search/dist/index.js +158 -12
- package/plugins/kk/commands/workflow-run.md +56 -18
- package/plugins/kk/decisions/kk-itc.yaml +46 -0
- package/plugins/kk/decisions/kk-seo-keyword.yaml +57 -0
- package/plugins/kk/decisions/kk-seo-page.yaml +230 -0
- package/plugins/kk/decisions/kk-seo-pair.yaml +21 -0
- package/plugins/kk/decisions/kk-seo-site.yaml +90 -0
- package/plugins/kk/plugin.json +1 -1
- package/plugins/kk/publish-presets/chinese-article.json +14 -0
- package/plugins/kk/publish-presets/technical-article.json +14 -0
- package/plugins/kk/references/smart-seo-attribution.md +85 -0
- package/plugins/kk/scripts/daily-stages.ts +42 -2
- package/plugins/kk/scripts/daily-voice-style.zh.md +1 -1
- package/plugins/kk/scripts/itc-stages.ts +25 -118
- package/plugins/kk/scripts/kk-workflow-stages.ts +38 -1
- package/plugins/kk/scripts/seo-decisions.ts +477 -0
- package/plugins/kk/scripts/seo-enrich.ts +728 -0
- package/plugins/kk/scripts/seo-facts.ts +610 -0
- package/plugins/kk/scripts/seo-fetch.ts +766 -0
- package/plugins/kk/scripts/seo-report.ts +460 -0
- package/plugins/kk/scripts/seo-rules.ts +1882 -0
- package/plugins/kk/scripts/seo-stages.ts +1044 -0
- package/plugins/kk/skills/article-adapt/SKILL.md +2 -2
- package/plugins/kk/skills/smart-seo/SKILL.md +183 -0
- package/plugins/kk/skills/smart-seo/references/method.md +126 -0
- package/plugins/kk/skills/smart-seo/references/narrative.md +125 -0
- package/plugins/kk/skills/smart-seo/references/operations.md +202 -0
- package/plugins/kk/skills/smart-seo/references/seo-geo-sources.md +90 -0
- package/plugins/kk/workflows/feature-verification.yaml +28 -24
- package/plugins/kk/workflows/kk-daily-ai-voice2.yaml +86 -18
- package/plugins/kk/workflows/kk-itc-author.yaml +406 -0
- package/plugins/kk/workflows/kk-itc.yaml +208 -682
- package/plugins/kk/workflows/kk-smart-seo.yaml +251 -0
- package/plugins/publishings/bilibili-pub/dist/index.js +21782 -0
- package/plugins/publishings/bilibili-pub/dist/profile-check.js +20410 -0
- package/plugins/publishings/bilibili-pub/package.json +20 -0
- package/plugins/publishings/bilibili-pub/plugin.json +12 -0
- package/plugins/publishings/bilibili-pub/src/flow.ts +1296 -0
- package/plugins/publishings/bilibili-pub/src/index.ts +139 -0
- package/plugins/publishings/bilibili-pub/src/profile-check.ts +19 -0
- package/plugins/publishings/bilibili-pub/src/selectors.ts +222 -0
- package/plugins/publishings/bilibili-pub/tsconfig.json +4 -0
- package/plugins/publishings/cnblogs-pub/dist/index.js +21383 -0
- package/plugins/publishings/cnblogs-pub/dist/profile-check.js +20412 -0
- package/plugins/publishings/cnblogs-pub/package.json +19 -0
- package/plugins/publishings/cnblogs-pub/plugin.json +12 -0
- package/plugins/publishings/cnblogs-pub/src/flow.ts +708 -0
- package/plugins/publishings/cnblogs-pub/src/index.ts +172 -0
- package/plugins/publishings/cnblogs-pub/src/profile-check.ts +24 -0
- package/plugins/publishings/cnblogs-pub/src/selectors.ts +104 -0
- package/plugins/publishings/cnblogs-pub/tsconfig.json +4 -0
- package/plugins/publishings/csdn-pub/dist/index.js +21552 -0
- package/plugins/publishings/csdn-pub/dist/profile-check.js +20963 -0
- package/plugins/publishings/csdn-pub/package.json +19 -0
- package/plugins/publishings/csdn-pub/plugin.json +12 -0
- package/plugins/publishings/csdn-pub/src/index.ts +1178 -0
- package/plugins/publishings/csdn-pub/src/profile-check.ts +23 -0
- package/plugins/publishings/csdn-pub/tsconfig.json +4 -0
- package/plugins/publishings/emdash-pub/dist/index.js +158 -12
- package/plugins/publishings/emdash-pub/plugin.json +22 -1
- package/plugins/publishings/infoq-pub/dist/index.js +160 -12
- package/plugins/publishings/infoq-pub/dist/profile-check.js +160 -12
- package/plugins/publishings/infoq-pub/plugin.json +21 -0
- package/plugins/publishings/jike-pub/dist/index.js +21379 -0
- package/plugins/publishings/jike-pub/dist/profile-check.js +20951 -0
- package/plugins/publishings/jike-pub/package.json +19 -0
- package/plugins/publishings/jike-pub/plugin.json +12 -0
- package/plugins/publishings/jike-pub/src/index.ts +800 -0
- package/plugins/publishings/jike-pub/src/profile-check.ts +21 -0
- package/plugins/publishings/jike-pub/tsconfig.json +4 -0
- package/plugins/publishings/juejin-pub/dist/index.js +160 -12
- package/plugins/publishings/juejin-pub/dist/profile-check.js +160 -12
- package/plugins/publishings/juejin-pub/plugin.json +21 -0
- package/plugins/publishings/medium-pub/dist/index.js +158 -12
- package/plugins/publishings/medium-pub/plugin.json +22 -1
- package/plugins/publishings/podcast-pub/dist/index.js +158 -12
- package/plugins/publishings/qiita-pub/dist/index.js +158 -12
- package/plugins/publishings/qiita-pub/plugin.json +24 -1
- package/plugins/publishings/shipinhao-pub/dist/index.js +21715 -0
- package/plugins/publishings/shipinhao-pub/dist/profile-check.js +20431 -0
- package/plugins/publishings/shipinhao-pub/package.json +19 -0
- package/plugins/publishings/shipinhao-pub/plugin.json +12 -0
- package/plugins/publishings/shipinhao-pub/src/flow.ts +1323 -0
- package/plugins/publishings/shipinhao-pub/src/index.ts +173 -0
- package/plugins/publishings/shipinhao-pub/src/profile-check.ts +25 -0
- package/plugins/publishings/shipinhao-pub/src/selectors.ts +241 -0
- package/plugins/publishings/shipinhao-pub/tsconfig.json +4 -0
- package/plugins/publishings/sspai-pub/dist/index.js +21371 -0
- package/plugins/publishings/sspai-pub/dist/profile-check.js +20414 -0
- package/plugins/publishings/sspai-pub/package.json +19 -0
- package/plugins/publishings/sspai-pub/plugin.json +12 -0
- package/plugins/publishings/sspai-pub/src/flow.ts +624 -0
- package/plugins/publishings/sspai-pub/src/index.ts +167 -0
- package/plugins/publishings/sspai-pub/src/profile-check.ts +25 -0
- package/plugins/publishings/sspai-pub/src/selectors.ts +122 -0
- package/plugins/publishings/sspai-pub/tsconfig.json +4 -0
- package/plugins/publishings/substack-pub/dist/index.js +160 -12
- package/plugins/publishings/substack-pub/dist/profile-check.js +160 -12
- package/plugins/publishings/substack-pub/plugin.json +21 -0
- package/plugins/publishings/surfdash-pub/dist/index.js +158 -12
- package/plugins/publishings/surfdash-pub/plugin.json +22 -1
- package/plugins/publishings/threads-pub/dist/index.js +158 -12
- package/plugins/publishings/wechatmp-pub/dist/index.js +1669 -502
- package/plugins/publishings/wechatmp-pub/dist/profile-check.js +204 -21
- package/plugins/publishings/wechatmp-pub/plugin.json +32 -0
- package/plugins/publishings/wechatmp-pub/src/cgi-draft.ts +540 -0
- package/plugins/publishings/wechatmp-pub/src/cgi-media.ts +380 -0
- package/plugins/publishings/wechatmp-pub/src/cgi.ts +485 -0
- package/plugins/publishings/wechatmp-pub/src/flow.ts +104 -0
- package/plugins/publishings/weibo-pub/dist/index.js +160 -12
- package/plugins/publishings/weibo-pub/dist/profile-check.js +160 -12
- package/plugins/publishings/weibo-pub/plugin.json +35 -0
- package/plugins/publishings/x-pub/dist/index.js +160 -12
- package/plugins/publishings/x-pub/dist/profile-check.js +160 -12
- package/plugins/publishings/x-pub/plugin.json +40 -0
- package/plugins/publishings/xhs-pub/dist/index.js +160 -12
- package/plugins/publishings/xhs-pub/dist/profile-check.js +160 -12
- package/plugins/publishings/xhs-pub/plugin.json +37 -0
- package/plugins/publishings/xiaoyuzhou-pub/dist/index.js +21491 -0
- package/plugins/publishings/xiaoyuzhou-pub/dist/profile-check.js +20417 -0
- package/plugins/publishings/xiaoyuzhou-pub/package.json +19 -0
- package/plugins/publishings/xiaoyuzhou-pub/plugin.json +12 -0
- package/plugins/publishings/xiaoyuzhou-pub/src/flow.ts +826 -0
- package/plugins/publishings/xiaoyuzhou-pub/src/index.ts +174 -0
- package/plugins/publishings/xiaoyuzhou-pub/src/profile-check.ts +26 -0
- package/plugins/publishings/xiaoyuzhou-pub/src/selectors.ts +125 -0
- package/plugins/publishings/xiaoyuzhou-pub/tsconfig.json +4 -0
- package/plugins/publishings/zenn-pub/dist/index.js +158 -12
- package/plugins/publishings/zenn-pub/plugin.json +22 -1
- package/plugins/generations/omni-voice-gen/voices/robin-news.wav +0 -0
|
@@ -12005,6 +12005,83 @@ import { createHash } from "crypto";
|
|
|
12005
12005
|
import { dirname as dirname2, join } from "path";
|
|
12006
12006
|
import { parseArgs } from "util";
|
|
12007
12007
|
|
|
12008
|
+
// ../../packages/kk-core/src/content-limits.ts
|
|
12009
|
+
var PLATFORM_CONTENT_LIMITS = Object.freeze({
|
|
12010
|
+
schemaVersion: 5,
|
|
12011
|
+
tagLimits: Object.freeze({
|
|
12012
|
+
default: 7,
|
|
12013
|
+
imageText: Object.freeze({
|
|
12014
|
+
instagram: 5,
|
|
12015
|
+
douyin: 5,
|
|
12016
|
+
kuaishou: 4,
|
|
12017
|
+
weixin: 1,
|
|
12018
|
+
xiaohongshu: 10
|
|
12019
|
+
}),
|
|
12020
|
+
shortVideo: Object.freeze({
|
|
12021
|
+
douyin: 5,
|
|
12022
|
+
kuaishou: 4,
|
|
12023
|
+
xiaohongshu: 10,
|
|
12024
|
+
bilibili: 10,
|
|
12025
|
+
zhihu: 5,
|
|
12026
|
+
tiktok: 20,
|
|
12027
|
+
youtube: 60
|
|
12028
|
+
})
|
|
12029
|
+
}),
|
|
12030
|
+
titleCapabilities: Object.freeze({
|
|
12031
|
+
dynamic: Object.freeze({
|
|
12032
|
+
bilibili: Object.freeze({ max: 20, unit: "utf16_code_units" }),
|
|
12033
|
+
zhihu: Object.freeze({ max: 50, unit: "utf16_code_units" }),
|
|
12034
|
+
douban: Object.freeze({ max: 70, unit: "utf16_code_units" }),
|
|
12035
|
+
x: null,
|
|
12036
|
+
threads: null,
|
|
12037
|
+
weibo: null,
|
|
12038
|
+
jike: null,
|
|
12039
|
+
zsxq: null,
|
|
12040
|
+
toutiao: null,
|
|
12041
|
+
juejin: null
|
|
12042
|
+
}),
|
|
12043
|
+
imageText: Object.freeze({
|
|
12044
|
+
xiaohongshu: Object.freeze({ max: 20, unit: "xiaohongshu_title_weighted" }),
|
|
12045
|
+
weixin: Object.freeze({ max: 20, unit: "utf16_code_units" }),
|
|
12046
|
+
douyin: Object.freeze({ max: 20, unit: "utf16_code_units" }),
|
|
12047
|
+
shipinhao: Object.freeze({ max: 22, unit: "utf16_code_units" }),
|
|
12048
|
+
reddit: Object.freeze({ max: 300, unit: "utf16_code_units" })
|
|
12049
|
+
}),
|
|
12050
|
+
article: Object.freeze({
|
|
12051
|
+
juejin: Object.freeze({ max: 100, unit: "utf16_code_units" }),
|
|
12052
|
+
csdn: Object.freeze({ max: 100, unit: "utf16_code_units" }),
|
|
12053
|
+
cnblogs: Object.freeze({ max: 128, unit: "utf16_code_units" }),
|
|
12054
|
+
weibo: Object.freeze({ max: 30, unit: "utf16_code_units" }),
|
|
12055
|
+
sspai: Object.freeze({ max: 80, unit: "utf16_code_units" })
|
|
12056
|
+
}),
|
|
12057
|
+
shortVideo: Object.freeze({
|
|
12058
|
+
shipinhao: Object.freeze({ max: 16, unit: "utf16_code_units" }),
|
|
12059
|
+
douyin: Object.freeze({ max: 30, unit: "utf16_code_units" }),
|
|
12060
|
+
bilibili: Object.freeze({ max: 80, unit: "utf16_code_units" })
|
|
12061
|
+
})
|
|
12062
|
+
}),
|
|
12063
|
+
bodyCapabilities: Object.freeze({
|
|
12064
|
+
dynamic: Object.freeze({
|
|
12065
|
+
threads: Object.freeze({ max: 500, unit: "unicode_code_points", behavior: "split_thread" }),
|
|
12066
|
+
x: Object.freeze({ max: 280, unit: "weighted", behavior: "split_thread" }),
|
|
12067
|
+
weibo: Object.freeze({ max: 2000, unit: "unicode_code_points" }),
|
|
12068
|
+
jike: Object.freeze({ max: 1000, unit: "unicode_code_points" })
|
|
12069
|
+
}),
|
|
12070
|
+
imageText: Object.freeze({
|
|
12071
|
+
xiaohongshu: Object.freeze({ max: 1000, unit: "unicode_code_points" }),
|
|
12072
|
+
douyin: Object.freeze({ max: 1000, unit: "unicode_code_points" })
|
|
12073
|
+
}),
|
|
12074
|
+
article: Object.freeze({
|
|
12075
|
+
wechatmp: Object.freeze({ max: 50000, unit: "unicode_code_points" }),
|
|
12076
|
+
juejin: Object.freeze({ max: 50000, unit: "unicode_code_points" })
|
|
12077
|
+
}),
|
|
12078
|
+
shortVideo: Object.freeze({
|
|
12079
|
+
douyin: Object.freeze({ max: 1000, unit: "unicode_code_points" }),
|
|
12080
|
+
kuaishou: Object.freeze({ max: 1000, unit: "unicode_code_points" }),
|
|
12081
|
+
shipinhao: Object.freeze({ max: 1000, unit: "unicode_code_points" })
|
|
12082
|
+
})
|
|
12083
|
+
})
|
|
12084
|
+
});
|
|
12008
12085
|
// ../../packages/kk-core/src/kinds.ts
|
|
12009
12086
|
init_zod();
|
|
12010
12087
|
|
|
@@ -12095,6 +12172,67 @@ var BrowserSessionDescriptorSchema = object({
|
|
|
12095
12172
|
}
|
|
12096
12173
|
}).optional()
|
|
12097
12174
|
}).strict();
|
|
12175
|
+
var ContentCountUnitSchema = _enum([
|
|
12176
|
+
"utf16_code_units",
|
|
12177
|
+
"unicode_code_points",
|
|
12178
|
+
"weighted",
|
|
12179
|
+
"xiaohongshu_title_weighted"
|
|
12180
|
+
]);
|
|
12181
|
+
var LimitEntrySchema = object({
|
|
12182
|
+
max: number2().int().positive(),
|
|
12183
|
+
unit: ContentCountUnitSchema
|
|
12184
|
+
}).strict();
|
|
12185
|
+
var PublishingProfileLimitsSchema = object({
|
|
12186
|
+
title: LimitEntrySchema.optional(),
|
|
12187
|
+
body: LimitEntrySchema.optional()
|
|
12188
|
+
}).strict();
|
|
12189
|
+
var PublishingProfileRequiresSchema = object({
|
|
12190
|
+
cover: boolean2().optional(),
|
|
12191
|
+
orderedImages: boolean2().optional()
|
|
12192
|
+
}).strict();
|
|
12193
|
+
var PublishingProfileModeBindingSchema = object({
|
|
12194
|
+
metadata: record(string2(), unknown())
|
|
12195
|
+
}).strict();
|
|
12196
|
+
var PublishingProfileModesSchema = object({
|
|
12197
|
+
draft: PublishingProfileModeBindingSchema.optional(),
|
|
12198
|
+
live: PublishingProfileModeBindingSchema.optional()
|
|
12199
|
+
}).strict().superRefine((modes, ctx) => {
|
|
12200
|
+
if (modes.draft === undefined && modes.live === undefined) {
|
|
12201
|
+
ctx.addIssue({
|
|
12202
|
+
code: "custom",
|
|
12203
|
+
message: 'modes must define at least one of "draft" or "live"'
|
|
12204
|
+
});
|
|
12205
|
+
}
|
|
12206
|
+
});
|
|
12207
|
+
var PublishingProfileSchema = object({
|
|
12208
|
+
format: string2().min(1),
|
|
12209
|
+
locale: string2().regex(/^(source|[a-z]{2,3}(-[A-Za-z0-9]+)*)$/, {
|
|
12210
|
+
message: 'locale must be "source" or a valid language tag'
|
|
12211
|
+
}),
|
|
12212
|
+
limits: PublishingProfileLimitsSchema.optional(),
|
|
12213
|
+
requires: PublishingProfileRequiresSchema.optional(),
|
|
12214
|
+
modes: PublishingProfileModesSchema
|
|
12215
|
+
}).strict();
|
|
12216
|
+
var PublishingCapabilitiesSchema = object({
|
|
12217
|
+
defaultProfile: string2().min(1),
|
|
12218
|
+
profiles: record(string2().regex(/^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/), PublishingProfileSchema)
|
|
12219
|
+
}).strict().superRefine((data, ctx) => {
|
|
12220
|
+
const keys = Object.keys(data.profiles);
|
|
12221
|
+
if (keys.length === 0) {
|
|
12222
|
+
ctx.addIssue({
|
|
12223
|
+
code: "custom",
|
|
12224
|
+
path: ["profiles"],
|
|
12225
|
+
message: "profiles record must be nonempty"
|
|
12226
|
+
});
|
|
12227
|
+
}
|
|
12228
|
+
if (!(data.defaultProfile in data.profiles)) {
|
|
12229
|
+
ctx.addIssue({
|
|
12230
|
+
code: "custom",
|
|
12231
|
+
path: ["defaultProfile"],
|
|
12232
|
+
message: `defaultProfile "${data.defaultProfile}" must reference a declared profile`
|
|
12233
|
+
});
|
|
12234
|
+
}
|
|
12235
|
+
});
|
|
12098
12236
|
var PluginManifestSchemaBase = looseObject({
|
|
12099
12237
|
name: string2().min(1),
|
|
12100
12238
|
kind: PluginKindSchema,
|
|
@@ -12103,23 +12241,31 @@ var PluginManifestSchemaBase = looseObject({
|
|
|
12103
12241
|
version: string2().optional(),
|
|
12104
12242
|
description: string2().optional(),
|
|
12105
12243
|
operations: record(string2(), PluginOperationSchema).optional(),
|
|
12106
|
-
browserSession: BrowserSessionDescriptorSchema.optional()
|
|
12244
|
+
browserSession: BrowserSessionDescriptorSchema.optional(),
|
|
12245
|
+
publishing: PublishingCapabilitiesSchema.optional()
|
|
12107
12246
|
});
|
|
12108
12247
|
var PluginManifestSchema = PluginManifestSchemaBase.superRefine((manifest, ctx) => {
|
|
12109
|
-
if (manifest.browserSession
|
|
12110
|
-
|
|
12111
|
-
|
|
12112
|
-
|
|
12113
|
-
|
|
12114
|
-
|
|
12115
|
-
|
|
12116
|
-
}
|
|
12248
|
+
if (manifest.browserSession !== undefined) {
|
|
12249
|
+
if (manifest.kind !== "publish") {
|
|
12250
|
+
ctx.addIssue({
|
|
12251
|
+
code: "custom",
|
|
12252
|
+
path: ["browserSession"],
|
|
12253
|
+
message: `browserSession requires kind "publish", not "${manifest.kind}"`
|
|
12254
|
+
});
|
|
12255
|
+
}
|
|
12256
|
+
if (manifest.check === undefined) {
|
|
12257
|
+
ctx.addIssue({
|
|
12258
|
+
code: "custom",
|
|
12259
|
+
path: ["browserSession"],
|
|
12260
|
+
message: "browserSession requires a check probe entry that owns the session routines"
|
|
12261
|
+
});
|
|
12262
|
+
}
|
|
12117
12263
|
}
|
|
12118
|
-
if (manifest.
|
|
12264
|
+
if (manifest.publishing !== undefined && manifest.kind !== "publish") {
|
|
12119
12265
|
ctx.addIssue({
|
|
12120
12266
|
code: "custom",
|
|
12121
|
-
path: ["
|
|
12122
|
-
message:
|
|
12267
|
+
path: ["publishing"],
|
|
12268
|
+
message: `publishing requires kind "publish", not "${manifest.kind}"`
|
|
12123
12269
|
});
|
|
12124
12270
|
}
|
|
12125
12271
|
});
|
|
@@ -33,12 +33,14 @@ Parse per the frozen rule:
|
|
|
33
33
|
- `--in <file>` → file mode. `--force` → overwrite an existing dest YAML / existing `brief.md`.
|
|
34
34
|
- Profile `kk-storm-research`: `--dir <path>` (default `$works_dir/kk-storm-research/<topic-id>`),
|
|
35
35
|
`--fixture` → force `fixture: "true"`.
|
|
36
|
-
- Profile `kk-itc`: `--dir <path>` (default `$works_dir/kk-itc/<kebab
|
|
37
|
-
`--
|
|
38
|
-
`--
|
|
39
|
-
`--
|
|
40
|
-
`--cover`, `--inline-images`, `--targets <a,b
|
|
41
|
-
`--source-locale en|zh|ja
|
|
36
|
+
- Profile `kk-itc`: `--dir <path>` (default `$works_dir/kk-itc/<kebab>[/<run-date>]`),
|
|
37
|
+
`--from-collect <topic-profile>` (a third source, XOR with `<topic>` / `--in`),
|
|
38
|
+
`--topic-profile <slug>`, `--run-date <YYYYMMDD>`, `--playbook generic|english|wechat`,
|
|
39
|
+
`--research`, `--judge`, `--outline <a|b|c>`, `--writer itc-generating|topic`, `--auto`,
|
|
40
|
+
`--unslop true|false`, `--max-revisions <N>`, `--cover`, `--inline-images`, `--targets <a,b>`,
|
|
41
|
+
`--publish-preset <name>`, `--seo off|handoff`, `--live`, `--source-locale en|zh|ja`. Unpassed
|
|
42
|
+
flags take `workflows.kk-itc` config, then compiled defaults (`generic`, `itc-generating`, `en`,
|
|
43
|
+
`seo: off`, max revisions `2`, booleans `false`) — resolved once by `itc-prepare` (§4).
|
|
42
44
|
`--fixture` passed with `kk-itc` or `kk-solo-podcast` → exit 1 (`fixture is storm-only`).
|
|
43
45
|
- Profile `kk-solo-podcast`: `--dir <path>` (default `$works_dir/kk-solo-podcast/<date>`), `--outline <a|b|c>`
|
|
44
46
|
(default empty), `--duration <min>` (default `8`), `--language <code>` (default `en`),
|
|
@@ -185,18 +187,51 @@ mkdir -p "$work_dir"
|
|
|
185
187
|
|
|
186
188
|
### Profile `kk-itc` (authoring workspace)
|
|
187
189
|
|
|
188
|
-
|
|
189
|
-
`
|
|
190
|
-
`
|
|
191
|
-
`--dir` still wins, and the default never writes into the caller's cwd.
|
|
190
|
+
The workspace and every config-backed option are resolved and **frozen** by
|
|
191
|
+
`kk stage run itc-prepare` (0303) — never re-derived here. Pre-generate the run id first, so the
|
|
192
|
+
frozen `itc-options.json` binds to the run that will consume it:
|
|
192
193
|
|
|
193
|
-
|
|
194
|
+
```bash
|
|
195
|
+
RUN_ID="kk-itc-$(date +%Y%m%dT%H%M%S)-$$"
|
|
196
|
+
launch="$(mktemp)"
|
|
197
|
+
# Unpassed flags stay "" and are dropped: they fall to workflows.kk-itc config, then compiled defaults.
|
|
198
|
+
jq -n --arg topic "$TOPIC" --arg inputFile "$INPUT_FILE" --arg fromCollect "$FROM_COLLECT" --arg dir "$DIR" \
|
|
199
|
+
--arg parentRunId "$RUN_ID" --arg topicProfile "$TOPIC_PROFILE" --arg runDate "$RUN_DATE" \
|
|
200
|
+
--arg writer "$WRITER" --arg playbook "$PLAYBOOK" --arg sourceLocale "$SOURCE_LOCALE" \
|
|
201
|
+
--arg publishTargets "$TARGETS" --arg publishPreset "$PRESET" --arg seo "$SEO" --arg maxRevisions "$MAX_REVISIONS" \
|
|
202
|
+
--arg research "$RESEARCH" --arg judge "$JUDGE" --arg auto "$AUTO" --arg unslop "$UNSLOP" --arg force "$FORCE" \
|
|
203
|
+
--arg publishLive "$LIVE" --arg coverEnabled "$COVER" --arg inlineImages "$INLINE_IMAGES" \
|
|
204
|
+
'$ARGS.named | with_entries(select(.value != ""))
|
|
205
|
+
| with_entries(if (.key | IN("research","judge","auto","unslop","force","publishLive","coverEnabled","inlineImages"))
|
|
206
|
+
then .value = (.value == "true") else . end)
|
|
207
|
+
| if has("maxRevisions") then .maxRevisions |= tonumber else . end' > "$launch"
|
|
208
|
+
work_dir=$(kk stage run itc-prepare --request "$launch" | jq -r '.workDir')
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
Exactly one of `topic` | `inputFile` | `fromCollect`. An invalid key, config file or source fails
|
|
212
|
+
before any workspace is written.
|
|
213
|
+
|
|
214
|
+
Binding (0153), applied once by `itc-prepare`: `--auto` binds `auto=true` and defaults `research`, `judge` and `unslop` to
|
|
194
215
|
`true` unless the operator passed them explicitly. `--live` is never implied — `publish_live`
|
|
195
216
|
stays `false` unless `--live` is passed explicitly (ADR-022). `--playbook wechat` without
|
|
196
217
|
`--source-locale` binds `source_locale=zh`; an explicit `--source-locale` always wins.
|
|
197
218
|
`--targets <a,b>` binds `publish_targets`; `--cover` / `--inline-images` bind
|
|
198
219
|
`cover_enabled` / `inline_images` (`false` unless passed); `--max-revisions` binds
|
|
199
|
-
`max_revisions` (default `2`).
|
|
220
|
+
`max_revisions` (default `2`). Each lands in `itc-options.json` under its camelCase key.
|
|
221
|
+
|
|
222
|
+
**Collected topic (`--from-collect <profile>`, 0299).** `itc-prepare` without `--chosen` returns
|
|
223
|
+
an *intake* snapshot (`status: intake`, `workDir: null`). Choose the topic in a run-scoped intake
|
|
224
|
+
dir, then finalize:
|
|
225
|
+
|
|
226
|
+
1. `kk stage run itc-topic-extract --request` `{parentRunId, intakeDir, topicProfile}` → the pool.
|
|
227
|
+
2. The agent writes `$intakeDir/topic-candidates.json` (≤3 candidates `a|b|c` with
|
|
228
|
+
`title`/`reason`/`itemIds` from the pool); `kk stage run itc-topic-validate --request`
|
|
229
|
+
`{parentRunId, intakeDir}` must pass.
|
|
230
|
+
3. `kk stage run itc-decision --topic "$intakeDir" "$RUN_ID"` prints the chosen id or `defer`.
|
|
231
|
+
**`defer` stops** — ask the operator to pick (never fall back to the first candidate).
|
|
232
|
+
4. `kk stage run itc-topic-select --request` `{parentRunId, intakeDir, selectedCandidateId}`.
|
|
233
|
+
5. `work_dir=$(kk stage run itc-prepare --request "$launch" --chosen "$intakeDir" | jq -r .workDir)`
|
|
234
|
+
finalizes the snapshot under the chosen title and copies the selection evidence into the workspace.
|
|
200
235
|
|
|
201
236
|
### Profile `kk-solo-podcast`
|
|
202
237
|
|
|
@@ -231,14 +266,17 @@ spur workflow run "$dest" --vars \
|
|
|
231
266
|
|
|
232
267
|
### Profile `kk-itc`
|
|
233
268
|
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
269
|
+
Launch under the **same** `RUN_ID` the snapshot was frozen for; the `prepare` node refuses a
|
|
270
|
+
snapshot owned by another run unless `force=true`. Downstream nodes read options from
|
|
271
|
+
`$work_dir/itc-options.json`, so the vars only locate the workspace and carry run-local inputs:
|
|
272
|
+
`work_dir`, `topic_profile`, `publish_preset`, `seo_mode`, `from_collect`, `run_date`, `outline`,
|
|
273
|
+
`force`, `rubric` (`tech-accuracy`), `agent`. The judge verdict lands at
|
|
274
|
+
`$work_dir/.itc-verdict.json`. A live plan with targets pauses at `send-confirm`: resuming
|
|
275
|
+
(`spur workflow continue $RUN_ID`) approves the send, cancelling rejects it.
|
|
238
276
|
|
|
239
277
|
```bash
|
|
240
|
-
spur workflow run "$dest" --vars \
|
|
241
|
-
"{\"
|
|
278
|
+
spur workflow run "$dest" --run-id "$RUN_ID" --vars \
|
|
279
|
+
"{\"work_dir\":\"$work_dir\",\"topic_profile\":\"$TOPIC_PROFILE\",\"publish_preset\":\"$PRESET\",\"seo_mode\":\"$SEO\",\"from_collect\":\"$FROM_COLLECT\",\"run_date\":\"$RUN_DATE\",\"outline\":\"$OUTLINE\",\"force\":\"$FORCE\",\"rubric\":\"tech-accuracy\",\"agent\":\"$AGENT\"}"
|
|
242
280
|
```
|
|
243
281
|
|
|
244
282
|
### Profile `kk-solo-podcast`
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
$schema: "@gobing-ai/spur/schemas/decision-catalog.schema.json"
|
|
2
|
+
version: 1
|
|
3
|
+
|
|
4
|
+
defaults:
|
|
5
|
+
minConfidence: 0
|
|
6
|
+
|
|
7
|
+
decisions:
|
|
8
|
+
kk-itc-topic-choice:
|
|
9
|
+
type: choice
|
|
10
|
+
description: Choose the strongest topic candidate from the candidate evidence pool, or defer to operator
|
|
11
|
+
parameters:
|
|
12
|
+
candidates:
|
|
13
|
+
type: string
|
|
14
|
+
description: Formatted candidate options with title, rationale, item IDs and source URLs
|
|
15
|
+
criteria:
|
|
16
|
+
a: Candidate slot a is the strongest and most cohesive technical article topic.
|
|
17
|
+
b: Candidate slot b is the strongest and most cohesive technical article topic.
|
|
18
|
+
c: Candidate slot c is the strongest and most cohesive technical article topic.
|
|
19
|
+
defer: Candidates are insufficient, contradictory, or need explicit operator review.
|
|
20
|
+
fallback: defer
|
|
21
|
+
|
|
22
|
+
kk-itc-outline-choice:
|
|
23
|
+
type: choice
|
|
24
|
+
description: Choose the best structured technical article outline option, or defer to operator
|
|
25
|
+
parameters:
|
|
26
|
+
options:
|
|
27
|
+
type: string
|
|
28
|
+
description: Candidate outline options with structure, headings, and rationale
|
|
29
|
+
criteria:
|
|
30
|
+
a: Outline option a has the strongest narrative arc and technical depth.
|
|
31
|
+
b: Outline option b has the strongest narrative arc and technical depth.
|
|
32
|
+
c: Outline option c has the strongest narrative arc and technical depth.
|
|
33
|
+
defer: Outlines require manual operator adjustment or refinement.
|
|
34
|
+
fallback: defer
|
|
35
|
+
|
|
36
|
+
kk-itc-preset-choice:
|
|
37
|
+
type: choice
|
|
38
|
+
description: Accept the suggested channel publication preset, or publish to no targets by default
|
|
39
|
+
parameters:
|
|
40
|
+
suggestion:
|
|
41
|
+
type: string
|
|
42
|
+
description: The recommended publication preset name and target channels
|
|
43
|
+
criteria:
|
|
44
|
+
suggested: Accept the suggested preset for publication.
|
|
45
|
+
none: Do not use the suggested preset; leave targets unselected.
|
|
46
|
+
fallback: none
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
$schema: "@gobing-ai/spur/schemas/decision-catalog.schema.json"
|
|
2
|
+
version: 1
|
|
3
|
+
|
|
4
|
+
defaults:
|
|
5
|
+
minConfidence: 0
|
|
6
|
+
|
|
7
|
+
decisions:
|
|
8
|
+
kk-seo-keyword-relevance:
|
|
9
|
+
type: score
|
|
10
|
+
description: Relevance of a keyword query to the target page content and topic.
|
|
11
|
+
parameters:
|
|
12
|
+
subject_id:
|
|
13
|
+
type: string
|
|
14
|
+
description: Keyword identifier or query string.
|
|
15
|
+
locale:
|
|
16
|
+
type: string
|
|
17
|
+
description: Target audience locale.
|
|
18
|
+
criteria:
|
|
19
|
+
- Unrelated or tangential keyword query with no relevance.
|
|
20
|
+
- Low relevance or secondary query with modest topical connection.
|
|
21
|
+
- Highly relevant keyword directly addressed by primary page content.
|
|
22
|
+
- Perfect primary target query with comprehensive topical alignment.
|
|
23
|
+
fallback: 0
|
|
24
|
+
|
|
25
|
+
kk-seo-keyword-other-brand:
|
|
26
|
+
type: noul
|
|
27
|
+
description: Whether the keyword query references a competitor or third-party brand.
|
|
28
|
+
parameters:
|
|
29
|
+
subject_id:
|
|
30
|
+
type: string
|
|
31
|
+
description: Keyword identifier or query string.
|
|
32
|
+
locale:
|
|
33
|
+
type: string
|
|
34
|
+
description: Target audience locale.
|
|
35
|
+
criteria:
|
|
36
|
+
"true": Query contains an explicit competitor brand, trademark, or proprietary product name.
|
|
37
|
+
"false": Query consists of generic, unbranded or owned brand search terms.
|
|
38
|
+
fallback: false
|
|
39
|
+
|
|
40
|
+
kk-seo-keyword-page:
|
|
41
|
+
type: choice
|
|
42
|
+
description: Mapping strategy for targeting this keyword query across site pages.
|
|
43
|
+
parameters:
|
|
44
|
+
subject_id:
|
|
45
|
+
type: string
|
|
46
|
+
description: Keyword identifier or query string.
|
|
47
|
+
locale:
|
|
48
|
+
type: string
|
|
49
|
+
description: Target audience locale.
|
|
50
|
+
candidates:
|
|
51
|
+
type: json
|
|
52
|
+
description: Serialized list of candidate page titles and URLs (max 30 candidates).
|
|
53
|
+
criteria:
|
|
54
|
+
existing: Map keyword to an existing candidate page that already best satisfies intent.
|
|
55
|
+
new: Create a dedicated new landing page or article to satisfy search intent.
|
|
56
|
+
unclear: Ambiguous intent, low commercial relevance, or insufficient evidence to map.
|
|
57
|
+
fallback: unclear
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
$schema: "@gobing-ai/spur/schemas/decision-catalog.schema.json"
|
|
2
|
+
version: 1
|
|
3
|
+
|
|
4
|
+
defaults:
|
|
5
|
+
minConfidence: 0
|
|
6
|
+
|
|
7
|
+
decisions:
|
|
8
|
+
kk-seo-page-type:
|
|
9
|
+
type: choice
|
|
10
|
+
description: Functional structural role of this webpage within the site.
|
|
11
|
+
parameters:
|
|
12
|
+
subject_id:
|
|
13
|
+
type: string
|
|
14
|
+
description: Canonical URL of the page.
|
|
15
|
+
locale:
|
|
16
|
+
type: string
|
|
17
|
+
description: Target audience locale.
|
|
18
|
+
criteria:
|
|
19
|
+
homepage: Primary domain root or brand entry point.
|
|
20
|
+
product: Specific item, merchandise or standalone paid SKU.
|
|
21
|
+
category: Collection, catalogue index, listing or facet filter page.
|
|
22
|
+
service: Specific professional or client service offering.
|
|
23
|
+
article: Editorial blog post, knowledge article, guide or news story.
|
|
24
|
+
landing: Targeted campaign, lead generation or conversion page.
|
|
25
|
+
about: Organization background, team or company history.
|
|
26
|
+
contact: Communication, physical location or support contact page.
|
|
27
|
+
policy: Terms of service, privacy policy or legal disclosure.
|
|
28
|
+
other: Functional page outside the standard classifications.
|
|
29
|
+
unclear: Ambiguous, mixed, or insufficient content signals.
|
|
30
|
+
fallback: unclear
|
|
31
|
+
|
|
32
|
+
kk-seo-search-intent:
|
|
33
|
+
type: choice
|
|
34
|
+
description: Primary user search intent targeted by this page.
|
|
35
|
+
parameters:
|
|
36
|
+
subject_id:
|
|
37
|
+
type: string
|
|
38
|
+
description: Canonical URL of the page.
|
|
39
|
+
locale:
|
|
40
|
+
type: string
|
|
41
|
+
description: Target audience locale.
|
|
42
|
+
criteria:
|
|
43
|
+
informational: User seeks knowledge, explanations, answers or tutorials.
|
|
44
|
+
navigational: User seeks to locate a specific brand, tool or destination.
|
|
45
|
+
commercial: User evaluates options, reviews, comparisons or solutions.
|
|
46
|
+
transactional: User is ready to purchase, subscribe, sign up or download.
|
|
47
|
+
mixed: Multiple distinct search intents addressed equally.
|
|
48
|
+
unclear: Ambiguous or undefined user intent.
|
|
49
|
+
fallback: unclear
|
|
50
|
+
|
|
51
|
+
kk-seo-page-action:
|
|
52
|
+
type: choice
|
|
53
|
+
description: Strategic editorial action recommended for this page.
|
|
54
|
+
parameters:
|
|
55
|
+
subject_id:
|
|
56
|
+
type: string
|
|
57
|
+
description: Canonical URL of the page.
|
|
58
|
+
locale:
|
|
59
|
+
type: string
|
|
60
|
+
description: Target audience locale.
|
|
61
|
+
criteria:
|
|
62
|
+
keep-or-improve: Valuable page worth retaining and updating incrementally.
|
|
63
|
+
rewrite: Substantive content overhaul required to meet search intent.
|
|
64
|
+
review-consolidation: Potential cannibalization or thin page to consolidate.
|
|
65
|
+
unclear: Insufficient evidence to determine strategic page action.
|
|
66
|
+
fallback: unclear
|
|
67
|
+
|
|
68
|
+
kk-seo-importance:
|
|
69
|
+
type: score
|
|
70
|
+
description: Strategic importance of this page to site search authority.
|
|
71
|
+
parameters:
|
|
72
|
+
subject_id:
|
|
73
|
+
type: string
|
|
74
|
+
description: Canonical URL of the page.
|
|
75
|
+
locale:
|
|
76
|
+
type: string
|
|
77
|
+
description: Target audience locale.
|
|
78
|
+
criteria:
|
|
79
|
+
- Incidental or utility page with negligible search potential.
|
|
80
|
+
- Secondary supporting page with modest targeted relevance.
|
|
81
|
+
- Core pillar or commercial page driving regular search authority.
|
|
82
|
+
- Essential primary asset or high-converting flagship page.
|
|
83
|
+
fallback: 0
|
|
84
|
+
|
|
85
|
+
kk-seo-helpfulness:
|
|
86
|
+
type: score
|
|
87
|
+
description: Depth and utility of the page content for human visitors.
|
|
88
|
+
parameters:
|
|
89
|
+
subject_id:
|
|
90
|
+
type: string
|
|
91
|
+
description: Canonical URL of the page.
|
|
92
|
+
locale:
|
|
93
|
+
type: string
|
|
94
|
+
description: Target audience locale.
|
|
95
|
+
criteria:
|
|
96
|
+
- Thin, repetitive or boilerplate text offering little value.
|
|
97
|
+
- Basic overview covering surface facts without original insight.
|
|
98
|
+
- Thorough and genuinely helpful content with practical utility.
|
|
99
|
+
- Exceptional, comprehensive resource with expert depth and clarity.
|
|
100
|
+
fallback: 0
|
|
101
|
+
|
|
102
|
+
kk-seo-specificity:
|
|
103
|
+
type: score
|
|
104
|
+
description: Precision and concrete focus of the topic discussion.
|
|
105
|
+
parameters:
|
|
106
|
+
subject_id:
|
|
107
|
+
type: string
|
|
108
|
+
description: Canonical URL of the page.
|
|
109
|
+
locale:
|
|
110
|
+
type: string
|
|
111
|
+
description: Target audience locale.
|
|
112
|
+
criteria:
|
|
113
|
+
- Vague, generic claims with no specific details or examples.
|
|
114
|
+
- Mostly general statements with a few isolated specifics.
|
|
115
|
+
- Concrete discussion with precise details, steps or terminology.
|
|
116
|
+
- Highly rigorous and exact specification with actionable details.
|
|
117
|
+
fallback: 0
|
|
118
|
+
|
|
119
|
+
kk-seo-trust:
|
|
120
|
+
type: score
|
|
121
|
+
description: Credibility, evidence and verifiable signals of expertise.
|
|
122
|
+
parameters:
|
|
123
|
+
subject_id:
|
|
124
|
+
type: string
|
|
125
|
+
description: Canonical URL of the page.
|
|
126
|
+
locale:
|
|
127
|
+
type: string
|
|
128
|
+
description: Target audience locale.
|
|
129
|
+
criteria:
|
|
130
|
+
- Unsubstantiated claims with zero sourcing or author attribution.
|
|
131
|
+
- Modest credibility signals with basic organizational context.
|
|
132
|
+
- Clear author expertise, cited sources, and verifiable claims.
|
|
133
|
+
- Authoritative industry benchmark with transparent methodology.
|
|
134
|
+
fallback: 0
|
|
135
|
+
|
|
136
|
+
kk-seo-citability:
|
|
137
|
+
type: score
|
|
138
|
+
description: Ease and likelihood of being quoted by answer engines.
|
|
139
|
+
parameters:
|
|
140
|
+
subject_id:
|
|
141
|
+
type: string
|
|
142
|
+
description: Canonical URL of the page.
|
|
143
|
+
locale:
|
|
144
|
+
type: string
|
|
145
|
+
description: Target audience locale.
|
|
146
|
+
criteria:
|
|
147
|
+
- Prose structure is unfocused and difficult to extract citations from.
|
|
148
|
+
- Contains extractable points buried in dense conversational prose.
|
|
149
|
+
- Clear, concise statements directly answering user questions.
|
|
150
|
+
- Structured, highly quotable definitions, data points and conclusions.
|
|
151
|
+
fallback: 0
|
|
152
|
+
|
|
153
|
+
kk-seo-title-fit:
|
|
154
|
+
type: score
|
|
155
|
+
description: How accurately the HTML title describes the page substance.
|
|
156
|
+
parameters:
|
|
157
|
+
subject_id:
|
|
158
|
+
type: string
|
|
159
|
+
description: Canonical URL of the page.
|
|
160
|
+
locale:
|
|
161
|
+
type: string
|
|
162
|
+
description: Target audience locale.
|
|
163
|
+
criteria:
|
|
164
|
+
- Title is misleading, irrelevant or clickbait disconnected from body.
|
|
165
|
+
- Title loosely matches body but misses primary topic emphasis.
|
|
166
|
+
- Title accurately reflects main subject and matches search intent.
|
|
167
|
+
- Title is concise, compelling and perfectly aligned with page content.
|
|
168
|
+
fallback: 0
|
|
169
|
+
|
|
170
|
+
kk-seo-meta-fit:
|
|
171
|
+
type: score
|
|
172
|
+
description: How accurately the meta description summarizes the page content.
|
|
173
|
+
parameters:
|
|
174
|
+
subject_id:
|
|
175
|
+
type: string
|
|
176
|
+
description: Canonical URL of the page.
|
|
177
|
+
locale:
|
|
178
|
+
type: string
|
|
179
|
+
description: Target audience locale.
|
|
180
|
+
criteria:
|
|
181
|
+
- Meta description is missing, generic or irrelevant.
|
|
182
|
+
- Description is partially relevant but lacks distinct proposition.
|
|
183
|
+
- Description clearly summarizes key page value and answers intent.
|
|
184
|
+
- Description is compelling, perfectly accurate and snippet-ready.
|
|
185
|
+
fallback: 0
|
|
186
|
+
|
|
187
|
+
kk-seo-answer-first:
|
|
188
|
+
type: noul
|
|
189
|
+
description: Whether the page answers the primary question early before the fold.
|
|
190
|
+
parameters:
|
|
191
|
+
subject_id:
|
|
192
|
+
type: string
|
|
193
|
+
description: Canonical URL of the page.
|
|
194
|
+
locale:
|
|
195
|
+
type: string
|
|
196
|
+
description: Target audience locale.
|
|
197
|
+
criteria:
|
|
198
|
+
"true": Direct answer or core conclusion appears in the opening section.
|
|
199
|
+
"false": Direct answer is buried deep after extensive filler or intro prose.
|
|
200
|
+
fallback: false
|
|
201
|
+
|
|
202
|
+
kk-seo-next-step:
|
|
203
|
+
type: noul
|
|
204
|
+
description: Whether the page guides the reader toward a clear next step or CTA.
|
|
205
|
+
parameters:
|
|
206
|
+
subject_id:
|
|
207
|
+
type: string
|
|
208
|
+
description: Canonical URL of the page.
|
|
209
|
+
locale:
|
|
210
|
+
type: string
|
|
211
|
+
description: Target audience locale.
|
|
212
|
+
criteria:
|
|
213
|
+
"true": Identifiable next action, link or relevant resource provided.
|
|
214
|
+
"false": Dead-end page with no contextual navigation or clear next step.
|
|
215
|
+
fallback: false
|
|
216
|
+
|
|
217
|
+
kk-seo-heading-fit:
|
|
218
|
+
type: noul
|
|
219
|
+
description: Whether the heading hierarchy accurately mirrors page topic flow.
|
|
220
|
+
parameters:
|
|
221
|
+
subject_id:
|
|
222
|
+
type: string
|
|
223
|
+
description: Canonical URL of the page.
|
|
224
|
+
locale:
|
|
225
|
+
type: string
|
|
226
|
+
description: Target audience locale.
|
|
227
|
+
criteria:
|
|
228
|
+
"true": Headings outline a coherent logical structure matching body sections.
|
|
229
|
+
"false": Headings are disorganized, misleading, decorative or missing.
|
|
230
|
+
fallback: false
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
$schema: "@gobing-ai/spur/schemas/decision-catalog.schema.json"
|
|
2
|
+
version: 1
|
|
3
|
+
|
|
4
|
+
defaults:
|
|
5
|
+
minConfidence: 0
|
|
6
|
+
|
|
7
|
+
decisions:
|
|
8
|
+
kk-seo-intent-overlap:
|
|
9
|
+
type: noul
|
|
10
|
+
description: Whether two sampled pages target substantially identical search intent and topic.
|
|
11
|
+
parameters:
|
|
12
|
+
subject_id:
|
|
13
|
+
type: string
|
|
14
|
+
description: Sorted pair identifier (pageA_id::pageB_id).
|
|
15
|
+
locale:
|
|
16
|
+
type: string
|
|
17
|
+
description: Target audience locale.
|
|
18
|
+
criteria:
|
|
19
|
+
"true": Both pages compete for the same primary query intent and cannibalize search authority.
|
|
20
|
+
"false": Pages serve distinct user queries or complementary stages of user intent.
|
|
21
|
+
fallback: false
|