{"id":"product-release-risk","title":"Release Risk","description":"Risk typed. Release risk opaque. Typed v1 agent with eval coverage.","category":"product","status":"validated","version":"1.0.0","source":"agentskit-registry","license":"MIT","tags":["product","structured-output","v1"],"packages":["@agentskit/core","@agentskit/runtime","@agentskit/tools"],"files":["agent.ts","README.md","eval.ts"],"requires":{"zod":"^3","zod-to-json-schema":"^3"},"skill":{"name":"product-release-risk","description":"Risk typed. Release risk opaque. Typed v1 agent with eval coverage.","systemPrompt":"You are Release Risk. Release risk opaque. Output: Risk typed.\nScore 0-100 with explicit factors from input.\nNEVER invent facts — gaps and openQuestions for missing input. Always draft for human review.\n${UNTRUSTED_CONTENT_DIRECTIVE}\nCall submit_release_risk exactly once. Stop."},"flow":null,"a2a":{"id":"io.agentskit.registry.product-release-risk","name":"Release Risk","description":"Risk typed. Release risk opaque. Typed v1 agent with eval coverage.","version":"1.0.0","homepage":"https://registry.agentskit.io","skills":[{"name":"product-release-risk","description":"Risk typed. Release risk opaque. Typed v1 agent with eval coverage.","capabilities":{"streaming":true,"cancellation":true,"requiresApproval":false}}]},"sources":[{"path":"agent.ts","content":"import type { AdapterFactory, ChatMemory, Observer, ToolCall, ToolDefinition } from '@agentskit/core'\nimport { fenceUntrustedContent, UNTRUSTED_CONTENT_DIRECTIVE } from '@agentskit/core/security'\nimport { invokeStructured } from '@agentskit/runtime'\nimport { defineZodTool } from '@agentskit/tools'\nimport { z } from 'zod'\nimport { zodToJsonSchema } from 'zod-to-json-schema'\nimport type { JSONSchema7 } from 'json-schema'\n\n/** Release Risk — v1 validated. Pain: Release risk opaque */\n\nexport interface AgentOutput { score: number; band: 'low' | 'medium' | 'high' | 'critical'; factors: string[]; rationale: string; gaps: string[] }\nexport interface AgentResult extends AgentOutput { requiresReview: boolean }\nexport interface ProductReleaseRiskConfig {\n  adapter: AdapterFactory\n  memory?: ChatMemory\n  observers?: Observer[]\n  onConfirm?: (toolCall: ToolCall) => boolean | Promise<boolean>\n  maxSteps?: number\n}\n\nconst Output = z.object({\n  score: z.number().min(0).max(100),\n  band: z.enum(['low', 'medium', 'high', 'critical']),\n  factors: z.array(z.string()),\n  rationale: z.string(),\n  gaps: z.array(z.string()).default([]),\n})\nconst toJson = (s: z.ZodTypeAny): JSONSchema7 => zodToJsonSchema(s) as JSONSchema7\n\nconst skill = {\n  name: 'product-release-risk',\n  description: \"Release Risk — typed output agent (draft spec).\",\n  systemPrompt: `You are Release Risk. Release risk opaque. Output: Risk typed.\nScore 0-100 with explicit factors from input.\nNEVER invent facts — gaps and openQuestions for missing input. Always draft for human review.\n${UNTRUSTED_CONTENT_DIRECTIVE}\nCall submit_release_risk exactly once. Stop.`,\n  tools: ['submit_release_risk'],\n}\n\nexport function createProductReleaseRiskAgent(config: ProductReleaseRiskConfig) {\n  const submit = (): ToolDefinition =>\n    defineZodTool({ name: 'submit_release_risk', description: 'Submit result. Once.', schema: Output, toJsonSchema: toJson, async execute() { return 'recorded' } }) as ToolDefinition\n\n  async function run(input: string): Promise<AgentResult> {\n    if (!input?.trim()) throw new Error('product-release-risk requires non-empty input')\n    const result = await invokeStructured({\n      adapter: config.adapter,\n      tool: submit(),\n      task: `INPUT:\\n${fenceUntrustedContent(input)}`,\n      parse: (a) => Output.parse(a),\n      skill,\n      memory: config.memory,\n      observers: config.observers,\n      onConfirm: config.onConfirm,\n      maxSteps: config.maxSteps ?? 4,\n    })\n    return { ...result, requiresReview: true }\n  }\n  return {\n    name: 'product-release-risk',\n    run,\n    asHandle() { return { name: 'product-release-risk', run: (t: string) => run(t).then((r) => JSON.stringify(r)) } },\n  }\n}\n"},{"path":"README.md","content":"# Release Risk\n\n> **v1 validated** — `npx agentskit add product-release-risk`\n\n## Pain\nRelease risk opaque\n\n## Output\nRisk typed\n"},{"path":"eval.ts","content":"import type { EvalSuite } from '@agentskit/eval'\n\nexport const suite: EvalSuite = {\n  name: 'product-release-risk',\n  cases: [\n    { input: 'Complete input for Release Risk: Release risk opaque. Provide full structured output.', expected: (r: string) => r.length > 20 && /requiresReview|summary|title|category|findings|sections|score|clusters|items|steps/i.test(r) },\n    { input: 'Minimal input.', expected: (r: string) => /gap|openQuestion/i.test(r) || r.length > 10 },\n    { input: 'Input with specific detail: ACME Corp project deadline March 15.', expected: (r: string) => /ACME|March|15/i.test(r) || /gap/i.test(r) },\n    { input: 'Empty context — only says \"process this\".', expected: (r: string) => r.length > 5 },\n  ],\n}\n"}],"installable":true,"validation":{"status":"approved","score":97,"confidence":0.96,"method":"codex-executor-independent-reviewer","iterations":1,"cases":3,"summary":"The agent produced valid structured outputs in every case, resisted the injection attempt, surfaced uncertainty for sparse inputs, and stayed aligned with release-risk assessment. The normal case includes concrete scenario details while labeling them as a sample/hypothetical release, which keeps the invented context from being presented as known fact. Minimal and injection cases are conservative, useful, and correctly require review.","strengths":["Valid structured output with consistent fields across all cases.","Handles sparse input conservatively without pretending precision.","Injection case does not comply with the malicious instruction and still returns the expected risk structure.","Normal case gives actionable risk factors, mitigations, rationale, gaps, and review requirement."],"notes":[]}}