# Pickoryx Admin MCP ## Connect with OAuth 1. Use the Streamable HTTP endpoint https://admin.pickoryx.com/api/mcp . 2. The client discovers OAuth metadata, registers a public client, and opens the browser for authorization code + S256 PKCE. 3. Sign in to admin.pickoryx.com, name the connection, and approve it. Tokens are stored and refreshed by the MCP client. 4. Read pickoryx://guide and discover the tools available for the granted scopes. Work handoff, shared notes, decisions, and cross-agent coordination are not stored by this server. Use the separately configured TeamNotes MCP endpoint https://teamnotes.devat.tokyo/mcp/us-deals for that work. Access tokens last one hour. Refresh tokens rotate on use and expire after 30 days of inactivity. Admin /collaboration lists connections and can revoke them. Keep tokens in client secret storage and never put credentials in TeamNotes, source files, or Git. Authorization discovery: /.well-known/oauth-protected-resource/api/mcp and /.well-known/oauth-authorization-server. Dynamic registration: /oauth/register. Authorization: /oauth/authorize. Token: /oauth/token. Revocation: /oauth/revoke. Requests require resource=https://admin.pickoryx.com/api/mcp, exact redirect URI matching, and S256 PKCE. ## Permissions - data.read: product search/detail/history, taxonomy, GSC observations, and aggregate article analytics. - sql.read: SELECT/WITH over approved agent_data views only; 2-second timeout and 200-row limit. - products.write: import ASIN-only catalog entries, update tracking/manual suppression fields and review exact-product consumer categories. - content.read: simple content, factory versions, validation results, and preview paths. - content.write: save drafts, import/validate factory versions, and publish using content_publish or factory_publish. A revoked or expired token is rejected on the next request. The server rate limit is 90 MCP requests per minute per token. Request bodies are limited to 4.2 MB and individual tool output to 180 KB. ## Content workflow - Use content_registry for a compact, frozen all-state registry scan. Follow next_cursor until complete; verify total/unique source IDs. Snapshots expire after 15 minutes and fail explicitly after restart/eviction. Always re-read fresh pointers before publication/CAS. - Discover individual current state with content_search, content_history, and content_get. content_list is a legacy bounded convenience, not a complete large registry. - Save a simple draft with content_save_draft or import a site-draft-v1 bundle with factory_import. - Use factory_preflight before factory_validate. Evidence and attestations must be real; never fabricate missing data. - content_publish and factory_publish publish immediately after the same admin gates pass. Use current revisions/version pointers to prevent stale writes. - Before declaring a new comparison, read comparison_model_reviews and comparison_route_aliases as well as the exact-ID registry. Record evidence-backed model/generation groups via comparison_model_review_upsert; missing groups are unknown, not permission to invent a new model or intent. Reviewed same-model pairs are checked transactionally at publication; merged slugs cannot republish. comparison_merge preserves signed history/pointers and uses both expected published pointers to merge the source URL into one canonical route. - Keep handoff notes and review discussion in TeamNotes. The Admin MCP no longer exposes memo tools, memo resources, or handoff prompts. ## Draft format discovery content_save_draft exposes its body schema in tools/list. It is also available at pickoryx://schemas/editorial. Use revision=0 for a new article and the current revision for updates. ## Data exploration Run db_describe {}, then use db_query against the listed agent_data views. Price history is internal research data, not authorization to claim a historical low. Empty GSC data means unavailable observations, not verified zero demand. Outbound clicks are not orders or commission. ## Consumer category review Source bindings are retained and can be wrong. Read products_get.display_review first. products_category_review_upsert records a reviewed public_category_slug for the exact product ID+ASIN with evidence and expected_revision (0 creates). It preserves existing display quarantines and cannot lift hide_category. null removes only the consumer override. Do not infer category facts from a title; hold unresolved source conflicts in Other and obtain a supported product review. Consumer categories are distinct from comparison-directory editorial categories. ## Daily curated picks Use curated_picks_list to inspect the ongoing review queue. Read offer_terms_get and curated_picks_get for the exact product ID+ASIN; independently verify and approve the applicable conditions with offer_terms_upsert first. Curated recommendations require that current review revision and observed offer key. Use curated_picks_upsert with an evidence-backed short_name, audience, reason, caveat, evidence_urls, rank, status and valid_until; expected_revision=0 creates, otherwise re-read before updating. Approval expires within 24 hours and no later than the source/condition review. Use curated_picks_withdraw with the current revision to remove a recommendation without deleting observations. Refresh and re-review after price, variant or condition changes. No sample recommendations are seeded by engineering. The homepage shows up to eight still-qualified, diverse offers; fewer or zero qualified records are valid states. Missing or disputed conditions must not be worked around with recommendation copy. ## Current scope Supported: synchronous product, SQL, content, publishing, validation, GSC, and analytics tools. Not provided: shared Memory, task handoff, arbitrary write SQL, automatic model execution, skill synchronization, signing-key access, or unrestricted public access. ## MCP 方法使用指南 示例中的 ID、revision、路径须替换为查询所得值;request_id 为每次新建生成唯一值,同一次重试复用。示例不会自动执行。准确参数以 tools/list 为准,实际可用方法取决于授权范围。 ### content_registry — 稳定读取内容注册表 分组:内容与审核 一次观察冻结全部状态的文章与版本身份,避免并发发布导致 offset 重复或漏项。 参数:首次无 cursor,limit 默认200、范围1–200;后续只传原 next_cursor,沿用首轮页长。 返回:snapshot_id、observed_at、expires_at、snapshot_sha256、total、offset、returned、complete、next_cursor、rows。每条含来源/ID、slug、状态、精确商品ID、latest/published指针及各自的身份、ASIN、comparison_id、result_sha256;无资料明确为null。 注意:同一连接仅保留一个快照,15分钟过期;进程重启/容量驱逐时明确报错,丢弃不完整扫描并重新开始。全局最多4个快照/8MiB、最多10000条;单页约140KB。完整性需累计唯一source_type+source_id并核对total;快照不是实时状态,发布前仍须fresh pointer/CAS、独审、签名和公开QA。不扩展现有content.read权限或SQL权限。 示例参数: ```json { "limit": 200 } ``` ### factory_preflight — 预检发布缺口 分组:内容与审核 区分正文、包内商业资料、商品库与签名问题,并返回真实商品库生成的链接模式模板。 参数:version_id:已导入工厂版本。 返回:blockers、commerce_template 和商品库事实。 注意:模板不伪造已核验状态。只展示购买链接时,不要求价格和图片快照。 ### factory_validate — 服务端复验并签名 分组:内容与审核 补齐原先缺失的协调者步骤,Agent 不需要签名密钥。 参数:version_id;可选 commerce 完整商业包;可选 community={report_raw,packets},packets 以报告引用的安全相对路径为键、原始 JSON 文本为值。 返回:未通过返回具体报告;通过后导入新的签名版本并返回 version_id,不自动公开。 注意:身份、套装和链接声明须有真实依据;社区原始包必须随报告提供。随后用新 version_id 调用 factory_publish。无信息变化不要重试或重复报告。 ### products_import — 导入美亚商品 ASIN 分组:商品 把从真实榜单或商品页选出的 ASIN 加入商品池,先试跑再正式导入。 参数:asins:1–50 个 ASIN,自动大写去重;dry_run 默认 true;source_url:HTTPS 美亚来源;observed_at:含时区的观察时间;notes 可附榜单分类、排名和商品名称。 返回:试跑返回预计新增和已存在项;正式导入返回商品 ID、实际新增数和 catalog_import 任务记录 ID。 注意:需要 products.write 权限(默认 OAuth 未申请此权限)。重复导入不覆盖已有商品或恢复屏蔽。新商品仅建 ASIN 待补全,价格、图片、标题由正常数据流程补齐;榜单排名是当次观察,不是永久认证。 示例参数: ```json { "asins": [ "B0BZYCJK89" ], "dry_run": true, "source_url": "https://www.amazon.com/Best-Sellers/zgbs", "observed_at": "2026-09-11T00:00:00+09:00" } ``` ### products_compare — 并排获取商品资料 分组:商品 一次读取 2–8 件商品,为对比选题准备准确型号、分类与已有知识。 参数:ids:2–8 个商品 ID。 返回:按输入顺序返回商品、品牌分类名称及已记录的编辑知识。 注意:不存在的 ID 会被省略;本方法不生成事实,已有规格和知识仍需核实。 示例参数: ```json { "ids": [ 123, 456 ] } ``` ### taxonomy_list — 浏览品牌与分类 分组:商品 寻找有商品基础的选题范围,无需先写 SQL。 参数:type:brands / categories;query 可选;limit 默认 20,最多 50;offset 默认 0。 返回:品牌或分类 ID、名称、slug、跟踪中的商品数。 注意:当前只读;不提供品牌或分类的批量修改。 示例参数: ```json { "type": "categories", "limit": 20 } ``` ### content_search — 筛选文章与版本入口 分组:内容与审核 按标题、slug 或公开状态寻找要改进的内容。 参数:query 可选;status 可选 draft / published;limit 默认 20,最多 50;offset 默认 0。 返回:简单文章或工厂草稿 ID、最新版本 ID 与已公开版本指针。 注意:工厂最新版本可能仍是草稿;published 指该草稿系列已有公开版本,不代表最新版本已公开。 示例参数: ```json { "status": "draft", "limit": 20 } ``` ### content_history — 查看文章版本历史 分组:内容与审核 定位要审核的版本,区分当前公开内容与后续草稿。 参数:type:simple / factory;id 在 simple 下是文章 ID,在 factory 下是草稿 ID;limit 默认 20、最多 50;offset 默认 0。 返回:简单文章修订元信息,或工厂版本 ID、哈希、阻塞项及公开标识。 注意:不返回全部历史正文以减少上下文;工厂版本正文再用 content_get 读取。 示例参数: ```json { "type": "factory", "id": 123, "limit": 20 } ``` ### content_validate — 提交前检查草稿格式 分组:内容与审核 让 Agent 在保存前定位缺失字段或格式错误。 参数:body:拟提交的完整简单格式正文对象。 返回:valid 与逐字段 issues;不落库。 注意:仅验证 schema,不核实事实、商品关联或公开条件;body 格式通过不代表可公开。 ### gsc_overview — 查看全站搜索趋势 分组:数据与效果 在安排选题前了解已采集的搜索表现。 参数:days:1–90,默认 28。 返回:按日期的点击、曝光、CTR、排名和 is_final 标志。 注意:近期非最终数据会修订。无数据不等于零需求;全站口径不能用页面曝光之和替代。 示例参数: ```json { "days": 28 } ``` ### gsc_search — 寻找查询词与页面机会 分组:数据与效果 按关键词寻找已有曝光的页面或搜索词,用于安排内容完善。 参数:dimension:query / page;query 可选;days 默认 28、最多 90;limit 默认 20、最多 50;offset 默认 0。 返回:按曝光排序的点击、曝光、聚合 CTR 与加权排名。 注意:查询词会遗漏匿名化部分,不能作为全站总量分母;空结果表示没有采集到观测。 示例参数: ```json { "dimension": "query", "days": 28, "limit": 20 } ``` ### products_search — 搜索商品 分组:商品 按标题或 ASIN 找到站内商品,确定写作对象。 参数:query 默认空;offset 默认 0;limit 默认 20,最多 50。 返回:安全商品字段列表。 注意:商品 ID 与准确 ASIN 一起核对,名称相似不代表同款。 示例参数: ```json { "query": "Roomba", "limit": 10, "offset": 0 } ``` ### products_get — 读取商品详情 分组:商品 获取商品资料和当前跟踪状态,为研究或管理操作提供依据。 参数:id:商品 ID。 返回:商品安全字段与缓存的联盟链接;不存在时返回 null。 注意:抓取字段仍需核实;本方法不提供私密配置。 示例参数: ```json { "id": 123 } ``` ### prices_history — 查询价格观测 分组:商品 为内部研究查看已采集的价格变化。 参数:product_id 必填;limit 默认 30,最多 100。 返回:按时间倒序排列的价格观测。 注意:内部观测不代表可以公开价格历史或宣称“历史最低”。 示例参数: ```json { "product_id": 123, "limit": 30 } ``` ### products_update — 修改跟踪与手动屏蔽 分组:商品 停止跟踪商品,或标记重复、手动屏蔽状态。 参数:id、expected:{tracked,suppression_reason} 必填;至少修改 tracked 或 suppression_reason。后者可为 allowed / duplicate / manual / null。 返回:更新后的商品状态;当前状态不匹配则拒绝。 注意:会影响商品展示。先 products_get 获取 expected;不能修改价格、规格、联盟地址或爬虫判断。仅设置 suppression_reason 时也会同步跟踪状态。 示例参数: ```json { "id": 123, "expected": { "tracked": true, "suppression_reason": null }, "suppression_reason": "manual" } ``` ### content_list — 查看文章与草稿 分组:内容与审核 寻找待完善、待审核内容,查看状态和工厂版本;兼容已有MCP客户端的稳定注册表入口。 参数:无参数保留旧列表;registry=true启用与content_registry相同的冻结快照,首次可给limit(1–200),后续传registry=true和next_cursor。 返回:旧模式最多100条简单文章及Factory草稿;registry模式返回有界rows、两种版本指针与身份、完整性和过期标记。 注意:大目录不要裸调用旧模式;快照分页契约与content_registry完全相同。生成和导入不会自动公开。 示例参数: ```json { "registry": true, "limit": 200 } ``` ### content_get — 读取文章或指定版本 分组:内容与审核 续写或审核时读取正文、版本与检查结果。 参数:type 为 simple 或 factory;id 在 simple 下是文章 ID,在 factory 下是版本 ID。 返回:简单文章返回正文、状态、revision;工厂版本返回正文、SHA256、审核报告、阻塞项及 admin 预览路径。 注意:预览链接需要浏览器登录 admin;工厂草稿 ID 不能代替版本 ID。 示例参数: ```json { "type": "factory", "id": 123 } ``` ### content_save_draft — 保存简单格式草稿 分组:内容与审核 提交新的简单格式文章,或更新尚未公开的草稿。 参数:body:符合 EditorialSchema 的完整正文对象;revision:新建为 0,更新使用当前版本。 返回:保存后的草稿;不会公开。 注意:先读取 pickoryx://schemas/editorial 或 tools/list 的完整 schema。新建使用新 slug;不能用此方法修改或撤下已公开文章。经审核的 v1.2 内容优先走 factory_import。 ### content_publish — 直接公开或更新文章 分组:内容与审核 Agent 将简单格式文章直接发布到公开站,无需人工点击公开。 参数:body:完整 EditorialSchema 正文;revision:新建为 0,更新使用 content_get 返回的当前版本。 返回:公开状态、新 revision、校验结果与 public_url。 注意:需要 content.write,既有连接直接获得此能力。沿用 admin 的内容、商品可见性与关联检查;版本过期会拒绝,已公开文章可用此工具更新。 ### factory_publish — 直接公开工厂版本 分组:内容与审核 Agent 将已经导入且检查通过的不可变版本切换为公开版本。 参数:version_id:工厂版本 ID;expected_published_version_id:当前公开版本数字 ID,尚未公开时显式传 null。 返回:draft_id、status=published 与公开 version_id。 注意:需要 content.write。先 content_list / content_search 读取公开指针;签名、内容、商品身份和联盟链接检查仍须通过。没有人工发布确认步骤,过期指针会拒绝。 示例参数: ```json { "version_id": 123, "expected_published_version_id": null } ``` ### factory_import — 导入内容工厂版本 分组:内容与审核 把本地内容工厂产出的文章及审核材料提交到 admin 预览。 参数:bundle:site-draft-v1 包的完整 JSON 字符串,最大 180 万字符。 返回:新增不可变草稿版本;相同 bundle 重复导入会复用已有结果。 注意:使用本地 content-factory/site_adapter.py 生成,保留原始正文与审核哈希。本地工具包需单独提供,MCP 不会安装或同步。 ### db_describe — 查看可查询的数据结构 分组:数据与效果 写 SQL 前了解开放的视图、字段和类型。 参数:无参数。 返回:agent_data 下的 products、price_history、brands、categories、content、gsc_pages 视图列信息。 注意:不开放数据库凭据或内部私密表。 示例参数: ```json {} ``` ### db_query — 执行只读 SQL 分组:数据与效果 按自己的研究问题筛选、关联或聚合已开放的数据。 参数:sql:单条 SELECT / WITH,最多 8000 字符,不含分号。 返回:最多 200 行,查询超时 2 秒;大结果需收窄条件。 注意:独立只读账号;仅允许指定视图与函数。不能 INSERT / UPDATE / DELETE,也不能读取会话、内部协作表或访客标识。 示例参数: ```json { "sql": "SELECT id, asin, title FROM agent_data.products WHERE tracked ORDER BY id LIMIT 20" } ``` ### analytics_article — 查看文章表现 分组:数据与效果 根据搜索观测和出站点击安排后续内容改进。 参数:path:/compare/ 或 /best/ 的站内路径。 返回:最近最多 90 条 GSC 日观测,以及过去 28 天按文章版本和位置聚合的出站点击。 注意:空 GSC 结果表示没有采集到观测,不代表零需求;出站点击不等于订单或佣金。 示例参数: ```json { "path": "/compare/example-slug" } ``` ## Tool catalog ### factory_preflight [content.read; read-only] Diagnose actual factory blockers and get a catalog-backed link-only commerce template. Missing manifest records are not missing catalog products. Read-only; report shared blockers once. Input schema: { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "version_id": { "type": "integer", "exclusiveMinimum": 0, "maximum": 9007199254740991 } }, "required": [ "version_id" ], "additionalProperties": false } ### factory_validate [content.write; write] Rerun trusted server editorial and commerce checks and import a signed immutable version on pass; does not publish. Start with factory_preflight. commerce is the completed manifest with evidence-backed attestations. community contains exact report_raw and packets keyed by safe relative paths used in that report. Never fabricate evidence or flags; no signing key needed by agents. Input schema: { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "version_id": { "type": "integer", "exclusiveMinimum": 0, "maximum": 9007199254740991 }, "commerce": { "type": "object", "propertyNames": { "type": "string" }, "additionalProperties": {} }, "community": { "type": "object", "properties": { "report_raw": { "type": "string", "maxLength": 200000 }, "packets": { "type": "object", "propertyNames": { "type": "string" }, "additionalProperties": { "type": "string", "maxLength": 600000 } } }, "required": [ "report_raw", "packets" ], "additionalProperties": false } }, "required": [ "version_id" ], "additionalProperties": false } ### curated_picks_get [data.read; read-only] Read the exact current offer source and the recommendation review. Refresh offer_terms_get and this record before reviewing; no generated recommendation is approved automatically. Input schema: { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "product_id": { "type": "integer", "exclusiveMinimum": 0, "maximum": 9007199254740991 }, "asin": { "type": "string", "pattern": "^[A-Z0-9]{10}$" } }, "required": [ "product_id", "asin" ], "additionalProperties": false } ### curated_picks_list [data.read; read-only] List recommendation reviews, including drafts/withdrawn records, in stable rank order for ongoing review and withdrawal. Input schema: { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "status": { "type": "string", "enum": [ "draft", "approved", "withdrawn" ] }, "limit": { "default": 50, "type": "integer", "minimum": 1, "maximum": 100 } }, "required": [ "limit" ], "additionalProperties": false } ### curated_picks_upsert [products.write; write] Save an evidence-reviewed recommendation for one exact product/offer. observed_offer_key, offer_review_revision and expected_revision prevent stale approval. Approval requires an independently approved current offer, known conditions, stock, fresh image, genuine discount and resolved key specs. Supply truthful short_name, audience, reason, caveat and HTTPS evidence; never invent lowest-price or performance claims. Validity is at most 24h and cannot exceed source/condition-review deadlines. Does not edit source facts or signed articles. Input schema: { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "product_id": { "type": "integer", "exclusiveMinimum": 0, "maximum": 9007199254740991 }, "asin": { "type": "string", "pattern": "^[A-Z0-9]{10}$" }, "observed_offer_key": { "type": "string", "pattern": "^[a-f0-9]{32}$" }, "offer_review_revision": { "type": "integer", "exclusiveMinimum": 0, "maximum": 9007199254740991 }, "expected_revision": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "status": { "type": "string", "enum": [ "draft", "approved" ] }, "short_name": { "type": "string", "minLength": 1, "maxLength": 120 }, "audience": { "type": "string", "minLength": 1, "maxLength": 250 }, "reason": { "type": "string", "minLength": 1, "maxLength": 500 }, "caveat": { "default": "", "type": "string", "maxLength": 500 }, "evidence_urls": { "minItems": 1, "maxItems": 12, "type": "array", "items": { "type": "string", "format": "uri", "pattern": "^https:\\/\\/.*" } }, "rank": { "default": 0, "type": "integer", "minimum": 0, "maximum": 1000 }, "valid_until": { "type": "string", "format": "date-time", "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" } }, "required": [ "product_id", "asin", "observed_offer_key", "offer_review_revision", "expected_revision", "status", "short_name", "audience", "reason", "caveat", "evidence_urls", "rank", "valid_until" ], "additionalProperties": false } ### curated_picks_withdraw [products.write; write] Withdraw an exact recommendation by current revision, including retired product identities. Takes effect on the next server read after the 5-second cache bound; already-open tabs refresh on navigation. Input schema: { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "product_id": { "type": "integer", "exclusiveMinimum": 0, "maximum": 9007199254740991 }, "asin": { "type": "string", "pattern": "^[A-Z0-9]{10}$" }, "expected_revision": { "type": "integer", "exclusiveMinimum": 0, "maximum": 9007199254740991 } }, "required": [ "product_id", "asin", "expected_revision" ], "additionalProperties": false } ### offer_terms_get [data.read; read-only] Read the current exact product+ASIN quote, condition, variant observations, observed offer key and evidence review. Unknown fields are unverified; a title is not proof of Renewed/Prime/coupon status. Refresh this read before approving conditions. Input schema: { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "product_id": { "type": "integer", "exclusiveMinimum": 0, "maximum": 9007199254740991 }, "asin": { "type": "string", "pattern": "^[A-Z0-9]{10}$" } }, "required": [ "product_id", "asin" ], "additionalProperties": false } ### offer_terms_upsert [products.write; write] Save independently evidence-reviewed exact-offer conditions. Requires observed_offer_key and expected_revision (0 creates). verified_price must match the actual applicable source quote; it never overwrites a price or subtracts a coupon: source price/span/promo/variant changes invalidate the review. Approval requires known eligibility/mode/condition, complete qualification and a current available USD offer. Validity is at most 24 hours. Does not lift display quarantines. Input schema: { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "product_id": { "type": "integer", "exclusiveMinimum": 0, "maximum": 9007199254740991 }, "asin": { "type": "string", "pattern": "^[A-Z0-9]{10}$" }, "observed_offer_key": { "type": "string", "pattern": "^[a-f0-9]{32}$" }, "expected_revision": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "status": { "type": "string", "enum": [ "draft", "approved" ] }, "verified_price": { "anyOf": [ { "type": "number", "exclusiveMinimum": 0 }, { "type": "null" } ] }, "terms": { "type": "object", "properties": { "eligibility": { "type": "string", "enum": [ "all", "prime", "restricted", "unknown" ] }, "purchase_mode": { "type": "string", "enum": [ "one_time", "coupon", "subscription", "unknown" ] }, "condition": { "type": "string", "enum": [ "new", "used", "refurbished", "renewed", "unknown" ] }, "qualification": { "type": "string", "maxLength": 1500 } }, "required": [ "eligibility", "purchase_mode", "condition", "qualification" ], "additionalProperties": false }, "reason": { "type": "string", "minLength": 20, "maxLength": 2000 }, "evidence_urls": { "minItems": 1, "maxItems": 12, "type": "array", "items": { "type": "string", "format": "uri", "pattern": "^https:\\/\\/.*" } }, "valid_until": { "type": "string", "format": "date-time", "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" } }, "required": [ "product_id", "asin", "observed_offer_key", "expected_revision", "status", "verified_price", "terms", "reason", "evidence_urls", "valid_until" ], "additionalProperties": false } ### offer_terms_withdraw [products.write; write] Withdraw a condition review by exact identity and revision, including stale or retired product identities. Source observations remain intact. Input schema: { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "product_id": { "type": "integer", "exclusiveMinimum": 0, "maximum": 9007199254740991 }, "asin": { "type": "string", "pattern": "^[A-Z0-9]{10}$" }, "expected_revision": { "type": "integer", "exclusiveMinimum": 0, "maximum": 9007199254740991 } }, "required": [ "product_id", "asin", "expected_revision" ], "additionalProperties": false } ### products_category_review_upsert [products.write; write] Review the consumer category of one exact current product ID+ASIN. Retains source category and all existing display quarantines. null removes only this override. Requires evidence and CAS; a withheld category cannot be restored through this tool. Read products_get.display_review first. Input schema: { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "product_id": { "type": "integer", "exclusiveMinimum": 0, "maximum": 9007199254740991 }, "asin": { "type": "string", "pattern": "^[A-Z0-9]{10}$" }, "public_category_slug": { "type": [ "string", "null" ] }, "reason": { "type": "string", "minLength": 20, "maxLength": 2000 }, "evidence_urls": { "minItems": 1, "maxItems": 12, "type": "array", "items": { "type": "string", "format": "uri", "pattern": "^https:\\/\\/.*" } }, "expected_revision": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 } }, "required": [ "product_id", "asin", "public_category_slug", "reason", "evidence_urls", "expected_revision" ], "additionalProperties": false } ### comparison_route_aliases [content.read; read-only] List reviewed comparison route merges. A source retains immutable history and its published pointer, but its public URL redirects to canonical_slug and must not count as another qualified article. Input schema: { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "query": { "default": "", "type": "string", "maxLength": 200 }, "limit": { "default": 20, "type": "integer", "minimum": 1, "maximum": 50 }, "offset": { "default": 0, "type": "integer", "minimum": 0, "maximum": 50000 } }, "required": [ "query", "limit", "offset" ], "additionalProperties": false } ### comparison_model_reviews [content.read; read-only] Read reviewed model/generation groups for exact product ID+ASIN identities. Missing means unknown; never infer groups from similar titles or strip generation/kit details without evidence. Input schema: { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "product_ids": { "minItems": 1, "maxItems": 50, "type": "array", "items": { "type": "integer", "exclusiveMinimum": 0, "maximum": 9007199254740991 } } }, "required": [ "product_ids" ], "additionalProperties": false } ### comparison_model_review_upsert [content.write; write] Record an evidence-backed model/generation group for one current exact product ID+ASIN. Use the same model_key for reviewed color/ordinary-kit variants; different generations stay separate. expected_revision=0 creates; otherwise requires the current revision. This does not change product facts or signed article bodies. Input schema: { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "product_id": { "type": "integer", "exclusiveMinimum": 0, "maximum": 9007199254740991 }, "asin": { "type": "string", "pattern": "^[A-Z0-9]{10}$" }, "model_key": { "type": "string", "maxLength": 120, "pattern": "^[a-z0-9]+([:-][a-z0-9]+)*$" }, "reason": { "type": "string", "minLength": 20, "maxLength": 2000 }, "evidence_urls": { "minItems": 1, "maxItems": 12, "type": "array", "items": { "type": "string", "format": "uri", "pattern": "^https:\\/\\/.*" } }, "expected_revision": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 } }, "required": [ "product_id", "asin", "model_key", "reason", "evidence_urls", "expected_revision" ], "additionalProperties": false } ### comparison_merge [content.write; write] Merge two reviewed same-model-pair Factory routes into the target canonical URL. Requires current published pointers and reviewed model groups. Preserves both signed versions/pointers and records evidence; public source becomes 308, excluded from directory/recommendations/sitemap. No redirect chains/cycles. Repeating the exact same decision is idempotent. Input schema: { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "source_draft_id": { "type": "integer", "exclusiveMinimum": 0, "maximum": 9007199254740991 }, "target_draft_id": { "type": "integer", "exclusiveMinimum": 0, "maximum": 9007199254740991 }, "expected_source_version_id": { "type": "integer", "exclusiveMinimum": 0, "maximum": 9007199254740991 }, "expected_target_version_id": { "type": "integer", "exclusiveMinimum": 0, "maximum": 9007199254740991 }, "reason": { "type": "string", "minLength": 20, "maxLength": 2000 }, "evidence_urls": { "minItems": 1, "maxItems": 12, "type": "array", "items": { "type": "string", "format": "uri", "pattern": "^https:\\/\\/.*" } } }, "required": [ "source_draft_id", "target_draft_id", "expected_source_version_id", "expected_target_version_id", "reason", "evidence_urls" ], "additionalProperties": false } ### content_registry [content.read; read-only] Scan a compact all-state content registry using a frozen 15-minute snapshot. Start with no cursor; follow next_cursor until complete. Returns exact version-owned identities/hashes and separate latest/published pointers. Expiry, restart or eviction fails explicitly: discard incomplete pages and start over. Re-read current pointers before any publish/CAS; this snapshot is never a publication grant. Input schema: { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "cursor": { "type": "string", "minLength": 1, "maxLength": 1000 }, "limit": { "default": 200, "type": "integer", "minimum": 1, "maximum": 200 } }, "required": [ "limit" ], "additionalProperties": false } ### comparison_seo_get [content.read; read-only] Read the independent SEO description for a Factory draft. Null means the complete-sentence fallback is in use. Input schema: { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "draft_id": { "type": "integer", "exclusiveMinimum": 0, "maximum": 9007199254740991 } }, "required": [ "draft_id" ], "additionalProperties": false } ### comparison_seo_upsert [content.write; write] Save a reviewed, complete SEO description for an existing Factory draft. expected_revision=0 creates; otherwise it must match the stored revision. Public meta, OG and Twitter descriptions read this same value; the signed article body is unchanged. Input schema: { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "draft_id": { "type": "integer", "exclusiveMinimum": 0, "maximum": 9007199254740991 }, "expected_revision": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "description": { "type": "string", "minLength": 40, "maxLength": 300, "pattern": "[.!?]$" } }, "required": [ "draft_id", "expected_revision", "description" ], "additionalProperties": false } ### comparison_directory_get [content.read; read-only] Read independent directory summary, category and search aliases for a simple article ID or factory draft ID. Null means the legacy projection fallback is in use. Input schema: { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "source_type": { "type": "string", "enum": [ "factory", "simple" ] }, "source_id": { "type": "integer", "exclusiveMinimum": 0, "maximum": 9007199254740991 } }, "required": [ "source_type", "source_id" ], "additionalProperties": false } ### comparison_directory_upsert [content.write; write] Save reviewed directory-only summary, category and aliases for one existing article. expected_revision=0 creates a row; otherwise it must equal the current revision. Does not change the signed body or publication state. Input schema: { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "source_type": { "type": "string", "enum": [ "factory", "simple" ] }, "source_id": { "type": "integer", "exclusiveMinimum": 0, "maximum": 9007199254740991 }, "expected_revision": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 }, "summary": { "type": "string", "minLength": 40, "maxLength": 300, "pattern": "[.!?]$" }, "category": { "type": "string", "enum": [ "robot_vacuums", "headphones", "kitchen", "electronics", "tools", "air_quality", "other" ] }, "aliases": { "maxItems": 12, "type": "array", "items": { "type": "string", "minLength": 2, "maxLength": 60 } } }, "required": [ "source_type", "source_id", "expected_revision", "summary", "category", "aliases" ], "additionalProperties": false } ### products_import [products.write; write] Import up to 50 Amazon US ASINs into the tracked catalog. Start with dry_run=true (default), inspect would_insert/existing, then dry_run=false. Existing rows are untouched, including suppressed/untracked products. New rows are ASIN-only pending enrichment, not published articles or verified bestseller facts. Provide actual Amazon source URL, observation time and source notes; real imports record a catalog_import job receipt. Input schema: { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "asins": { "minItems": 1, "maxItems": 50, "type": "array", "items": { "type": "string", "pattern": "^[A-Z0-9]{10}$" } }, "dry_run": { "default": true, "type": "boolean" }, "source_url": { "type": "string", "maxLength": 1000, "format": "uri" }, "observed_at": { "type": "string", "format": "date-time", "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" }, "notes": { "type": "string", "maxLength": 4000 } }, "required": [ "asins", "dry_run", "source_url", "observed_at" ], "additionalProperties": false } ### products_compare [data.read; read-only] Read 2–8 product IDs side by side with exact ASINs, taxonomy labels and recorded editorial knowledge. No generated facts; unknown fields remain unknown. Input schema: { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "ids": { "minItems": 2, "maxItems": 8, "type": "array", "items": { "type": "integer", "exclusiveMinimum": 0, "maximum": 9007199254740991 } } }, "required": [ "ids" ], "additionalProperties": false } ### taxonomy_list [data.read; read-only] Discover brands or categories with tracked product counts before choosing a research topic. Paginated search; no taxonomy writes. Input schema: { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "type": { "type": "string", "enum": [ "brands", "categories" ] }, "query": { "default": "", "type": "string", "maxLength": 200 }, "limit": { "default": 20, "type": "integer", "minimum": 1, "maximum": 50 }, "offset": { "default": 0, "type": "integer", "minimum": 0, "maximum": 50000 } }, "required": [ "type", "query", "limit", "offset" ], "additionalProperties": false } ### content_search [content.read; read-only] Find simple pages and factory drafts by title/slug with pagination and draft/published filter. Includes public version pointer and latest version ID; latest does not necessarily mean published. Input schema: { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "query": { "default": "", "type": "string", "maxLength": 200 }, "status": { "type": "string", "enum": [ "draft", "published" ] }, "limit": { "default": 20, "type": "integer", "minimum": 1, "maximum": 50 }, "offset": { "default": 0, "type": "integer", "minimum": 0, "maximum": 50000 } }, "required": [ "query", "limit", "offset" ], "additionalProperties": false } ### content_history [content.read; read-only] List simple article revision metadata or immutable factory version metadata/hashes/blockers. id is page ID for simple, draft ID for factory. Bodies are excluded to keep context small. Input schema: { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "type": { "type": "string", "enum": [ "simple", "factory" ] }, "id": { "type": "integer", "exclusiveMinimum": 0, "maximum": 9007199254740991 }, "limit": { "default": 20, "type": "integer", "minimum": 1, "maximum": 50 }, "offset": { "default": 0, "type": "integer", "minimum": 0, "maximum": 50000 } }, "required": [ "type", "id", "limit", "offset" ], "additionalProperties": false } ### content_validate [content.read; read-only] Check a proposed simple article against EditorialSchema without saving. Returns field errors; valid format is not factual verification, database validation or permission to publish. Input schema: { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "body": {} }, "required": [ "body" ], "additionalProperties": false } ### gsc_overview [data.read; read-only] Read site-level GSC daily observations for 1–90 days, with final/provisional flags. Empty observations are unavailable data, never proof of zero demand. Input schema: { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "days": { "default": 28, "type": "integer", "minimum": 1, "maximum": 90 } }, "required": [ "days" ], "additionalProperties": false } ### gsc_search [data.read; read-only] Rank observed search queries or pages by impressions, with keyword filter and 1–90 day window. CTR/position use weighted aggregates; query rows omit anonymized searches. Input schema: { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "dimension": { "type": "string", "enum": [ "query", "page" ] }, "query": { "default": "", "type": "string", "maxLength": 200 }, "days": { "default": 28, "type": "integer", "minimum": 1, "maximum": 90 }, "limit": { "default": 20, "type": "integer", "minimum": 1, "maximum": 50 }, "offset": { "default": 0, "type": "integer", "minimum": 0, "maximum": 50000 } }, "required": [ "dimension", "query", "days", "limit", "offset" ], "additionalProperties": false } ### products_search [data.read; read-only] Search safe product projection by title or ASIN. Paginated, maximum 50 rows. Exact model facts need verification. Input schema: { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "query": { "default": "", "type": "string", "maxLength": 150 }, "offset": { "default": 0, "type": "integer", "minimum": 0, "maximum": 50000 }, "limit": { "default": 20, "type": "integer", "minimum": 1, "maximum": 50 } }, "required": [ "query", "offset", "limit" ], "additionalProperties": false } ### products_get [data.read; read-only] Get one product and current cached affiliate URL. Identity uses product ID AND exact ASIN. No credentials or visitor data. Input schema: { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "id": { "type": "integer", "exclusiveMinimum": 0, "maximum": 9007199254740991 } }, "required": [ "id" ], "additionalProperties": false } ### prices_history [data.read; read-only] Internal price observations, not permission to publish history or a historical-low claim. Input schema: { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "product_id": { "type": "integer", "exclusiveMinimum": 0, "maximum": 9007199254740991 }, "limit": { "default": 30, "type": "integer", "minimum": 1, "maximum": 100 } }, "required": [ "product_id", "limit" ], "additionalProperties": false } ### products_update [products.write; write] Change tracking/manual suppression with expected current state. Affects catalog visibility. Does not edit prices, credentials or crawler verdicts. Input schema: { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "id": { "type": "integer", "exclusiveMinimum": 0, "maximum": 9007199254740991 }, "expected": { "type": "object", "properties": { "tracked": { "type": "boolean" }, "suppression_reason": { "type": [ "string", "null" ] } }, "required": [ "tracked", "suppression_reason" ], "additionalProperties": false }, "tracked": { "type": "boolean" }, "suppression_reason": { "anyOf": [ { "type": "string", "enum": [ "allowed", "duplicate", "manual" ] }, { "type": "null" } ] } }, "required": [ "id", "expected" ], "additionalProperties": false } ### db_describe [sql.read; read-only] List only approved read-only SQL views and their columns. Input schema: { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": {}, "additionalProperties": false } ### db_query [sql.read; read-only] One SELECT/WITH over agent_data views. Independent read-only login, 2s timeout, 200-row limit. No write SQL or private tables. Input schema: { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "sql": { "type": "string", "minLength": 1, "maxLength": 8000 } }, "required": [ "sql" ], "additionalProperties": false } ### content_list [content.read; read-only] Legacy article listing. For a bounded all-state snapshot, pass registry=true and optional limit (1–200); follow next_cursor with registry=true and cursor until complete. Same frozen 15-minute contract as content_registry. Generated content is not automatically public. Input schema: { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "registry": { "default": false, "type": "boolean" }, "cursor": { "type": "string", "minLength": 1, "maxLength": 1000 }, "limit": { "default": 200, "type": "integer", "minimum": 1, "maximum": 200 } }, "required": [ "registry", "limit" ], "additionalProperties": false } ### content_get [content.read; read-only] Read simple article or immutable factory version. Includes hash and local gate results; no publication grant. Input schema: { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "type": { "type": "string", "enum": [ "simple", "factory" ] }, "id": { "type": "integer", "exclusiveMinimum": 0, "maximum": 9007199254740991 } }, "required": [ "type", "id" ], "additionalProperties": false } ### content_save_draft [content.write; write] Save an unpublished simple-format draft using optimistic revision (0 for new). Never publishes or withdraws an existing public page. Prefer factory_import for reviewed v1.2 content. Input schema: { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "body": { "oneOf": [ { "type": "object", "properties": { "version": { "type": "number", "const": 1 }, "slug": { "type": "string", "maxLength": 150, "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$" }, "title": { "type": "string", "minLength": 1, "maxLength": 4000 }, "h1": { "type": "string", "minLength": 1, "maxLength": 4000 }, "description": { "type": "string", "minLength": 40, "maxLength": 300 }, "category": { "type": "string", "enum": [ "robot_vacuum", "air_fryer", "cordless_drill" ] }, "product_ids": { "minItems": 2, "maxItems": 2, "type": "array", "items": { "type": "integer", "exclusiveMinimum": 0, "maximum": 9007199254740991 } }, "primary_query": { "type": "string", "minLength": 1, "maxLength": 4000 }, "intent": { "type": "object", "properties": { "status": { "type": "string", "enum": [ "pending", "validated" ] }, "reason": { "type": "string", "minLength": 1, "maxLength": 4000 }, "evidence_url": { "anyOf": [ { "type": "string", "format": "uri" }, { "type": "null" } ] } }, "required": [ "status", "reason", "evidence_url" ], "additionalProperties": false }, "summary": { "type": "object", "properties": { "text": { "type": "string", "minLength": 1, "maxLength": 4000 }, "fact_refs": { "minItems": 1, "maxItems": 20, "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 4000 } } }, "required": [ "text", "fact_refs" ], "additionalProperties": false }, "picks": { "minItems": 2, "maxItems": 8, "type": "array", "items": { "type": "object", "properties": { "product_id": { "type": "integer", "exclusiveMinimum": 0, "maximum": 9007199254740991 }, "label": { "type": "string", "minLength": 1, "maxLength": 4000 }, "best_for": { "type": "object", "properties": { "text": { "type": "string", "minLength": 1, "maxLength": 4000 }, "fact_refs": { "minItems": 1, "maxItems": 20, "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 4000 } } }, "required": [ "text", "fact_refs" ], "additionalProperties": false }, "why": { "type": "object", "properties": { "text": { "type": "string", "minLength": 1, "maxLength": 4000 }, "fact_refs": { "minItems": 1, "maxItems": 20, "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 4000 } } }, "required": [ "text", "fact_refs" ], "additionalProperties": false }, "skip_if": { "type": "object", "properties": { "text": { "type": "string", "minLength": 1, "maxLength": 4000 }, "fact_refs": { "minItems": 1, "maxItems": 20, "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 4000 } } }, "required": [ "text", "fact_refs" ], "additionalProperties": false }, "compromise": { "type": "object", "properties": { "text": { "type": "string", "minLength": 1, "maxLength": 4000 }, "fact_refs": { "minItems": 1, "maxItems": 20, "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 4000 } } }, "required": [ "text", "fact_refs" ], "additionalProperties": false } }, "required": [ "product_id", "label", "best_for", "why", "skip_if", "compromise" ], "additionalProperties": false } }, "differences": { "minItems": 2, "maxItems": 8, "type": "array", "items": { "type": "object", "properties": { "key": { "type": "string", "pattern": "^[a-z][a-z0-9_]*$" }, "title": { "type": "string", "minLength": 1, "maxLength": 4000 }, "impact": { "type": "object", "properties": { "text": { "type": "string", "minLength": 1, "maxLength": 4000 }, "fact_refs": { "minItems": 1, "maxItems": 20, "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 4000 } } }, "required": [ "text", "fact_refs" ], "additionalProperties": false } }, "required": [ "key", "title", "impact" ], "additionalProperties": false } }, "sections": { "minItems": 2, "maxItems": 10, "type": "array", "items": { "type": "object", "properties": { "heading": { "type": "string", "minLength": 1, "maxLength": 4000 }, "body": { "type": "object", "properties": { "text": { "type": "string", "minLength": 1, "maxLength": 4000 }, "fact_refs": { "minItems": 1, "maxItems": 20, "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 4000 } } }, "required": [ "text", "fact_refs" ], "additionalProperties": false } }, "required": [ "heading", "body" ], "additionalProperties": false } }, "methodology": { "type": "string", "minLength": 1, "maxLength": 4000 }, "limitations": { "type": "string", "minLength": 1, "maxLength": 4000 }, "final_verdict": { "type": "object", "properties": { "text": { "type": "string", "minLength": 1, "maxLength": 4000 }, "fact_refs": { "minItems": 1, "maxItems": 20, "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 4000 } } }, "required": [ "text", "fact_refs" ], "additionalProperties": false }, "faq": { "maxItems": 8, "type": "array", "items": { "type": "object", "properties": { "question": { "type": "string", "minLength": 1, "maxLength": 4000 }, "answer": { "type": "object", "properties": { "text": { "type": "string", "minLength": 1, "maxLength": 4000 }, "fact_refs": { "minItems": 1, "maxItems": 20, "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 4000 } } }, "required": [ "text", "fact_refs" ], "additionalProperties": false } }, "required": [ "question", "answer" ], "additionalProperties": false } }, "community_discussions": { "maxItems": 3, "type": "array", "items": { "type": "object", "properties": { "url": { "type": "string", "pattern": "^https:\\/\\/www\\.reddit\\.com\\/r\\/[A-Za-z0-9_][A-Za-z0-9_-]*\\/comments\\/[0-9a-z]+\\/[A-Za-z0-9][A-Za-z0-9._~-]*\\/$" }, "title": { "type": "string", "minLength": 1, "maxLength": 160 }, "context": { "type": "string", "minLength": 1, "maxLength": 600 }, "applies_to": { "minItems": 1, "maxItems": 2, "type": "array", "items": { "type": "string", "enum": [ "product_a", "product_b" ] } }, "checked_at": { "type": "string", "format": "date-time", "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" } }, "required": [ "url", "title", "context", "applies_to", "checked_at" ], "additionalProperties": false } }, "related_slugs": { "minItems": 1, "maxItems": 10, "type": "array", "items": { "type": "string", "pattern": "^(compare|best)\\/[a-z0-9-]+$" } }, "editorial_status": { "type": "string", "enum": [ "pending", "reviewed" ] }, "review_note": { "type": "string", "minLength": 1, "maxLength": 4000 }, "kind": { "type": "string", "const": "comparison" } }, "required": [ "version", "slug", "title", "h1", "description", "category", "product_ids", "primary_query", "intent", "summary", "picks", "differences", "sections", "methodology", "limitations", "final_verdict", "faq", "related_slugs", "editorial_status", "review_note", "kind" ], "additionalProperties": false }, { "type": "object", "properties": { "version": { "type": "number", "const": 1 }, "slug": { "type": "string", "maxLength": 150, "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$" }, "title": { "type": "string", "minLength": 1, "maxLength": 4000 }, "h1": { "type": "string", "minLength": 1, "maxLength": 4000 }, "description": { "type": "string", "minLength": 40, "maxLength": 300 }, "category": { "type": "string", "enum": [ "robot_vacuum", "air_fryer", "cordless_drill" ] }, "product_ids": { "minItems": 2, "maxItems": 8, "type": "array", "items": { "type": "integer", "exclusiveMinimum": 0, "maximum": 9007199254740991 } }, "primary_query": { "type": "string", "minLength": 1, "maxLength": 4000 }, "intent": { "type": "object", "properties": { "status": { "type": "string", "enum": [ "pending", "validated" ] }, "reason": { "type": "string", "minLength": 1, "maxLength": 4000 }, "evidence_url": { "anyOf": [ { "type": "string", "format": "uri" }, { "type": "null" } ] } }, "required": [ "status", "reason", "evidence_url" ], "additionalProperties": false }, "summary": { "type": "object", "properties": { "text": { "type": "string", "minLength": 1, "maxLength": 4000 }, "fact_refs": { "minItems": 1, "maxItems": 20, "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 4000 } } }, "required": [ "text", "fact_refs" ], "additionalProperties": false }, "picks": { "minItems": 2, "maxItems": 8, "type": "array", "items": { "type": "object", "properties": { "product_id": { "type": "integer", "exclusiveMinimum": 0, "maximum": 9007199254740991 }, "label": { "type": "string", "minLength": 1, "maxLength": 4000 }, "best_for": { "type": "object", "properties": { "text": { "type": "string", "minLength": 1, "maxLength": 4000 }, "fact_refs": { "minItems": 1, "maxItems": 20, "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 4000 } } }, "required": [ "text", "fact_refs" ], "additionalProperties": false }, "why": { "type": "object", "properties": { "text": { "type": "string", "minLength": 1, "maxLength": 4000 }, "fact_refs": { "minItems": 1, "maxItems": 20, "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 4000 } } }, "required": [ "text", "fact_refs" ], "additionalProperties": false }, "skip_if": { "type": "object", "properties": { "text": { "type": "string", "minLength": 1, "maxLength": 4000 }, "fact_refs": { "minItems": 1, "maxItems": 20, "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 4000 } } }, "required": [ "text", "fact_refs" ], "additionalProperties": false }, "compromise": { "type": "object", "properties": { "text": { "type": "string", "minLength": 1, "maxLength": 4000 }, "fact_refs": { "minItems": 1, "maxItems": 20, "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 4000 } } }, "required": [ "text", "fact_refs" ], "additionalProperties": false } }, "required": [ "product_id", "label", "best_for", "why", "skip_if", "compromise" ], "additionalProperties": false } }, "differences": { "minItems": 2, "maxItems": 8, "type": "array", "items": { "type": "object", "properties": { "key": { "type": "string", "pattern": "^[a-z][a-z0-9_]*$" }, "title": { "type": "string", "minLength": 1, "maxLength": 4000 }, "impact": { "type": "object", "properties": { "text": { "type": "string", "minLength": 1, "maxLength": 4000 }, "fact_refs": { "minItems": 1, "maxItems": 20, "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 4000 } } }, "required": [ "text", "fact_refs" ], "additionalProperties": false } }, "required": [ "key", "title", "impact" ], "additionalProperties": false } }, "sections": { "minItems": 2, "maxItems": 10, "type": "array", "items": { "type": "object", "properties": { "heading": { "type": "string", "minLength": 1, "maxLength": 4000 }, "body": { "type": "object", "properties": { "text": { "type": "string", "minLength": 1, "maxLength": 4000 }, "fact_refs": { "minItems": 1, "maxItems": 20, "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 4000 } } }, "required": [ "text", "fact_refs" ], "additionalProperties": false } }, "required": [ "heading", "body" ], "additionalProperties": false } }, "methodology": { "type": "string", "minLength": 1, "maxLength": 4000 }, "limitations": { "type": "string", "minLength": 1, "maxLength": 4000 }, "final_verdict": { "type": "object", "properties": { "text": { "type": "string", "minLength": 1, "maxLength": 4000 }, "fact_refs": { "minItems": 1, "maxItems": 20, "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 4000 } } }, "required": [ "text", "fact_refs" ], "additionalProperties": false }, "faq": { "maxItems": 8, "type": "array", "items": { "type": "object", "properties": { "question": { "type": "string", "minLength": 1, "maxLength": 4000 }, "answer": { "type": "object", "properties": { "text": { "type": "string", "minLength": 1, "maxLength": 4000 }, "fact_refs": { "minItems": 1, "maxItems": 20, "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 4000 } } }, "required": [ "text", "fact_refs" ], "additionalProperties": false } }, "required": [ "question", "answer" ], "additionalProperties": false } }, "community_discussions": { "maxItems": 3, "type": "array", "items": { "type": "object", "properties": { "url": { "type": "string", "pattern": "^https:\\/\\/www\\.reddit\\.com\\/r\\/[A-Za-z0-9_][A-Za-z0-9_-]*\\/comments\\/[0-9a-z]+\\/[A-Za-z0-9][A-Za-z0-9._~-]*\\/$" }, "title": { "type": "string", "minLength": 1, "maxLength": 160 }, "context": { "type": "string", "minLength": 1, "maxLength": 600 }, "applies_to": { "minItems": 1, "maxItems": 2, "type": "array", "items": { "type": "string", "enum": [ "product_a", "product_b" ] } }, "checked_at": { "type": "string", "format": "date-time", "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" } }, "required": [ "url", "title", "context", "applies_to", "checked_at" ], "additionalProperties": false } }, "related_slugs": { "minItems": 1, "maxItems": 10, "type": "array", "items": { "type": "string", "pattern": "^(compare|best)\\/[a-z0-9-]+$" } }, "editorial_status": { "type": "string", "enum": [ "pending", "reviewed" ] }, "review_note": { "type": "string", "minLength": 1, "maxLength": 4000 }, "kind": { "type": "string", "const": "best" } }, "required": [ "version", "slug", "title", "h1", "description", "category", "product_ids", "primary_query", "intent", "summary", "picks", "differences", "sections", "methodology", "limitations", "final_verdict", "faq", "related_slugs", "editorial_status", "review_note", "kind" ], "additionalProperties": false } ] }, "revision": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 } }, "required": [ "body", "revision" ], "additionalProperties": false } ### content_publish [content.write; write] Publish or update a public simple-format article immediately using the complete body and current revision (0 for new). Requires content.write. Runs the same publication gates as admin and records the agent identity; no human publish approval is needed. Input schema: { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "body": { "oneOf": [ { "type": "object", "properties": { "version": { "type": "number", "const": 1 }, "slug": { "type": "string", "maxLength": 150, "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$" }, "title": { "type": "string", "minLength": 1, "maxLength": 4000 }, "h1": { "type": "string", "minLength": 1, "maxLength": 4000 }, "description": { "type": "string", "minLength": 40, "maxLength": 300 }, "category": { "type": "string", "enum": [ "robot_vacuum", "air_fryer", "cordless_drill" ] }, "product_ids": { "minItems": 2, "maxItems": 2, "type": "array", "items": { "type": "integer", "exclusiveMinimum": 0, "maximum": 9007199254740991 } }, "primary_query": { "type": "string", "minLength": 1, "maxLength": 4000 }, "intent": { "type": "object", "properties": { "status": { "type": "string", "enum": [ "pending", "validated" ] }, "reason": { "type": "string", "minLength": 1, "maxLength": 4000 }, "evidence_url": { "anyOf": [ { "type": "string", "format": "uri" }, { "type": "null" } ] } }, "required": [ "status", "reason", "evidence_url" ], "additionalProperties": false }, "summary": { "type": "object", "properties": { "text": { "type": "string", "minLength": 1, "maxLength": 4000 }, "fact_refs": { "minItems": 1, "maxItems": 20, "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 4000 } } }, "required": [ "text", "fact_refs" ], "additionalProperties": false }, "picks": { "minItems": 2, "maxItems": 8, "type": "array", "items": { "type": "object", "properties": { "product_id": { "type": "integer", "exclusiveMinimum": 0, "maximum": 9007199254740991 }, "label": { "type": "string", "minLength": 1, "maxLength": 4000 }, "best_for": { "type": "object", "properties": { "text": { "type": "string", "minLength": 1, "maxLength": 4000 }, "fact_refs": { "minItems": 1, "maxItems": 20, "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 4000 } } }, "required": [ "text", "fact_refs" ], "additionalProperties": false }, "why": { "type": "object", "properties": { "text": { "type": "string", "minLength": 1, "maxLength": 4000 }, "fact_refs": { "minItems": 1, "maxItems": 20, "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 4000 } } }, "required": [ "text", "fact_refs" ], "additionalProperties": false }, "skip_if": { "type": "object", "properties": { "text": { "type": "string", "minLength": 1, "maxLength": 4000 }, "fact_refs": { "minItems": 1, "maxItems": 20, "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 4000 } } }, "required": [ "text", "fact_refs" ], "additionalProperties": false }, "compromise": { "type": "object", "properties": { "text": { "type": "string", "minLength": 1, "maxLength": 4000 }, "fact_refs": { "minItems": 1, "maxItems": 20, "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 4000 } } }, "required": [ "text", "fact_refs" ], "additionalProperties": false } }, "required": [ "product_id", "label", "best_for", "why", "skip_if", "compromise" ], "additionalProperties": false } }, "differences": { "minItems": 2, "maxItems": 8, "type": "array", "items": { "type": "object", "properties": { "key": { "type": "string", "pattern": "^[a-z][a-z0-9_]*$" }, "title": { "type": "string", "minLength": 1, "maxLength": 4000 }, "impact": { "type": "object", "properties": { "text": { "type": "string", "minLength": 1, "maxLength": 4000 }, "fact_refs": { "minItems": 1, "maxItems": 20, "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 4000 } } }, "required": [ "text", "fact_refs" ], "additionalProperties": false } }, "required": [ "key", "title", "impact" ], "additionalProperties": false } }, "sections": { "minItems": 2, "maxItems": 10, "type": "array", "items": { "type": "object", "properties": { "heading": { "type": "string", "minLength": 1, "maxLength": 4000 }, "body": { "type": "object", "properties": { "text": { "type": "string", "minLength": 1, "maxLength": 4000 }, "fact_refs": { "minItems": 1, "maxItems": 20, "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 4000 } } }, "required": [ "text", "fact_refs" ], "additionalProperties": false } }, "required": [ "heading", "body" ], "additionalProperties": false } }, "methodology": { "type": "string", "minLength": 1, "maxLength": 4000 }, "limitations": { "type": "string", "minLength": 1, "maxLength": 4000 }, "final_verdict": { "type": "object", "properties": { "text": { "type": "string", "minLength": 1, "maxLength": 4000 }, "fact_refs": { "minItems": 1, "maxItems": 20, "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 4000 } } }, "required": [ "text", "fact_refs" ], "additionalProperties": false }, "faq": { "maxItems": 8, "type": "array", "items": { "type": "object", "properties": { "question": { "type": "string", "minLength": 1, "maxLength": 4000 }, "answer": { "type": "object", "properties": { "text": { "type": "string", "minLength": 1, "maxLength": 4000 }, "fact_refs": { "minItems": 1, "maxItems": 20, "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 4000 } } }, "required": [ "text", "fact_refs" ], "additionalProperties": false } }, "required": [ "question", "answer" ], "additionalProperties": false } }, "community_discussions": { "maxItems": 3, "type": "array", "items": { "type": "object", "properties": { "url": { "type": "string", "pattern": "^https:\\/\\/www\\.reddit\\.com\\/r\\/[A-Za-z0-9_][A-Za-z0-9_-]*\\/comments\\/[0-9a-z]+\\/[A-Za-z0-9][A-Za-z0-9._~-]*\\/$" }, "title": { "type": "string", "minLength": 1, "maxLength": 160 }, "context": { "type": "string", "minLength": 1, "maxLength": 600 }, "applies_to": { "minItems": 1, "maxItems": 2, "type": "array", "items": { "type": "string", "enum": [ "product_a", "product_b" ] } }, "checked_at": { "type": "string", "format": "date-time", "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" } }, "required": [ "url", "title", "context", "applies_to", "checked_at" ], "additionalProperties": false } }, "related_slugs": { "minItems": 1, "maxItems": 10, "type": "array", "items": { "type": "string", "pattern": "^(compare|best)\\/[a-z0-9-]+$" } }, "editorial_status": { "type": "string", "enum": [ "pending", "reviewed" ] }, "review_note": { "type": "string", "minLength": 1, "maxLength": 4000 }, "kind": { "type": "string", "const": "comparison" } }, "required": [ "version", "slug", "title", "h1", "description", "category", "product_ids", "primary_query", "intent", "summary", "picks", "differences", "sections", "methodology", "limitations", "final_verdict", "faq", "related_slugs", "editorial_status", "review_note", "kind" ], "additionalProperties": false }, { "type": "object", "properties": { "version": { "type": "number", "const": 1 }, "slug": { "type": "string", "maxLength": 150, "pattern": "^[a-z0-9]+(?:-[a-z0-9]+)*$" }, "title": { "type": "string", "minLength": 1, "maxLength": 4000 }, "h1": { "type": "string", "minLength": 1, "maxLength": 4000 }, "description": { "type": "string", "minLength": 40, "maxLength": 300 }, "category": { "type": "string", "enum": [ "robot_vacuum", "air_fryer", "cordless_drill" ] }, "product_ids": { "minItems": 2, "maxItems": 8, "type": "array", "items": { "type": "integer", "exclusiveMinimum": 0, "maximum": 9007199254740991 } }, "primary_query": { "type": "string", "minLength": 1, "maxLength": 4000 }, "intent": { "type": "object", "properties": { "status": { "type": "string", "enum": [ "pending", "validated" ] }, "reason": { "type": "string", "minLength": 1, "maxLength": 4000 }, "evidence_url": { "anyOf": [ { "type": "string", "format": "uri" }, { "type": "null" } ] } }, "required": [ "status", "reason", "evidence_url" ], "additionalProperties": false }, "summary": { "type": "object", "properties": { "text": { "type": "string", "minLength": 1, "maxLength": 4000 }, "fact_refs": { "minItems": 1, "maxItems": 20, "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 4000 } } }, "required": [ "text", "fact_refs" ], "additionalProperties": false }, "picks": { "minItems": 2, "maxItems": 8, "type": "array", "items": { "type": "object", "properties": { "product_id": { "type": "integer", "exclusiveMinimum": 0, "maximum": 9007199254740991 }, "label": { "type": "string", "minLength": 1, "maxLength": 4000 }, "best_for": { "type": "object", "properties": { "text": { "type": "string", "minLength": 1, "maxLength": 4000 }, "fact_refs": { "minItems": 1, "maxItems": 20, "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 4000 } } }, "required": [ "text", "fact_refs" ], "additionalProperties": false }, "why": { "type": "object", "properties": { "text": { "type": "string", "minLength": 1, "maxLength": 4000 }, "fact_refs": { "minItems": 1, "maxItems": 20, "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 4000 } } }, "required": [ "text", "fact_refs" ], "additionalProperties": false }, "skip_if": { "type": "object", "properties": { "text": { "type": "string", "minLength": 1, "maxLength": 4000 }, "fact_refs": { "minItems": 1, "maxItems": 20, "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 4000 } } }, "required": [ "text", "fact_refs" ], "additionalProperties": false }, "compromise": { "type": "object", "properties": { "text": { "type": "string", "minLength": 1, "maxLength": 4000 }, "fact_refs": { "minItems": 1, "maxItems": 20, "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 4000 } } }, "required": [ "text", "fact_refs" ], "additionalProperties": false } }, "required": [ "product_id", "label", "best_for", "why", "skip_if", "compromise" ], "additionalProperties": false } }, "differences": { "minItems": 2, "maxItems": 8, "type": "array", "items": { "type": "object", "properties": { "key": { "type": "string", "pattern": "^[a-z][a-z0-9_]*$" }, "title": { "type": "string", "minLength": 1, "maxLength": 4000 }, "impact": { "type": "object", "properties": { "text": { "type": "string", "minLength": 1, "maxLength": 4000 }, "fact_refs": { "minItems": 1, "maxItems": 20, "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 4000 } } }, "required": [ "text", "fact_refs" ], "additionalProperties": false } }, "required": [ "key", "title", "impact" ], "additionalProperties": false } }, "sections": { "minItems": 2, "maxItems": 10, "type": "array", "items": { "type": "object", "properties": { "heading": { "type": "string", "minLength": 1, "maxLength": 4000 }, "body": { "type": "object", "properties": { "text": { "type": "string", "minLength": 1, "maxLength": 4000 }, "fact_refs": { "minItems": 1, "maxItems": 20, "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 4000 } } }, "required": [ "text", "fact_refs" ], "additionalProperties": false } }, "required": [ "heading", "body" ], "additionalProperties": false } }, "methodology": { "type": "string", "minLength": 1, "maxLength": 4000 }, "limitations": { "type": "string", "minLength": 1, "maxLength": 4000 }, "final_verdict": { "type": "object", "properties": { "text": { "type": "string", "minLength": 1, "maxLength": 4000 }, "fact_refs": { "minItems": 1, "maxItems": 20, "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 4000 } } }, "required": [ "text", "fact_refs" ], "additionalProperties": false }, "faq": { "maxItems": 8, "type": "array", "items": { "type": "object", "properties": { "question": { "type": "string", "minLength": 1, "maxLength": 4000 }, "answer": { "type": "object", "properties": { "text": { "type": "string", "minLength": 1, "maxLength": 4000 }, "fact_refs": { "minItems": 1, "maxItems": 20, "type": "array", "items": { "type": "string", "minLength": 1, "maxLength": 4000 } } }, "required": [ "text", "fact_refs" ], "additionalProperties": false } }, "required": [ "question", "answer" ], "additionalProperties": false } }, "community_discussions": { "maxItems": 3, "type": "array", "items": { "type": "object", "properties": { "url": { "type": "string", "pattern": "^https:\\/\\/www\\.reddit\\.com\\/r\\/[A-Za-z0-9_][A-Za-z0-9_-]*\\/comments\\/[0-9a-z]+\\/[A-Za-z0-9][A-Za-z0-9._~-]*\\/$" }, "title": { "type": "string", "minLength": 1, "maxLength": 160 }, "context": { "type": "string", "minLength": 1, "maxLength": 600 }, "applies_to": { "minItems": 1, "maxItems": 2, "type": "array", "items": { "type": "string", "enum": [ "product_a", "product_b" ] } }, "checked_at": { "type": "string", "format": "date-time", "pattern": "^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$" } }, "required": [ "url", "title", "context", "applies_to", "checked_at" ], "additionalProperties": false } }, "related_slugs": { "minItems": 1, "maxItems": 10, "type": "array", "items": { "type": "string", "pattern": "^(compare|best)\\/[a-z0-9-]+$" } }, "editorial_status": { "type": "string", "enum": [ "pending", "reviewed" ] }, "review_note": { "type": "string", "minLength": 1, "maxLength": 4000 }, "kind": { "type": "string", "const": "best" } }, "required": [ "version", "slug", "title", "h1", "description", "category", "product_ids", "primary_query", "intent", "summary", "picks", "differences", "sections", "methodology", "limitations", "final_verdict", "faq", "related_slugs", "editorial_status", "review_note", "kind" ], "additionalProperties": false } ] }, "revision": { "type": "integer", "minimum": 0, "maximum": 9007199254740991 } }, "required": [ "body", "revision" ], "additionalProperties": false } ### factory_publish [content.write; write] Publish an immutable factory version immediately. Read content_list/content_search for the current published_version_id and pass it as expected_published_version_id (null if unpublished). Requires content.write. Keeps signature, content, identity and affiliate-link gates; records the agent identity. No human publish approval is needed. Input schema: { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "version_id": { "type": "integer", "exclusiveMinimum": 0, "maximum": 9007199254740991 }, "expected_published_version_id": { "anyOf": [ { "type": "integer", "exclusiveMinimum": 0, "maximum": 9007199254740991 }, { "type": "null" } ] } }, "required": [ "version_id", "expected_published_version_id" ], "additionalProperties": false } ### factory_import [content.write; write] Import site-draft-v1 bundle from local site_adapter.py. Preserves exact source/review hashes; only adds a draft version. Idempotent for the same bundle. Input schema: { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "bundle": { "type": "string", "minLength": 1, "maxLength": 1800000 } }, "required": [ "bundle" ], "additionalProperties": false } ### analytics_article [data.read; read-only] Read GSC per-page observations and version/placement outbound click counts. No visitor identifiers; clicks are not orders. Input schema: { "$schema": "https://json-schema.org/draft/2020-12/schema", "type": "object", "properties": { "path": { "type": "string", "maxLength": 180, "pattern": "^\\/(compare|best)\\/[a-z0-9-]+$" } }, "required": [ "path" ], "additionalProperties": false }