From 6aabdc6359f6bb4bad08cd08dc8453fdf898fe5e Mon Sep 17 00:00:00 2001 From: LubuSeb <187313664+LubuSeb@users.noreply.github.com> Date: Tue, 23 Jun 2026 07:11:09 +0200 Subject: [PATCH 1/3] Add RFP response skill --- skills/rfp-response/SKILL.md | 63 ++++ skills/rfp-response/X.yaml | 104 ++++++ .../rfp-response/evidence/dogfood-output.json | 348 ++++++++++++++++++ .../evidence/dogfood-output.stderr.txt | 0 .../evidence/dogfood-receipts-linux.tgz | Bin 0 -> 1501 bytes .../evidence/local-harness-receipts-linux.tgz | Bin 0 -> 1830 bytes .../evidence/local-harness-verification.json | 22 ++ .../local-harness-verification.stderr.txt | 0 .../rfp-response/evidence/local-harness.json | 15 + .../evidence/local-harness.stderr.txt | 0 skills/rfp-response/evidence/runx-version.txt | 1 + .../rfp-response/evidence/verification.json | 15 + .../evidence/verification.stderr.txt | 0 .../fixtures/supported-questionnaire.json | 36 ++ .../fixtures/unsupported-questionnaire.json | 26 ++ skills/rfp-response/run.mjs | 192 ++++++++++ 16 files changed, 822 insertions(+) create mode 100644 skills/rfp-response/SKILL.md create mode 100644 skills/rfp-response/X.yaml create mode 100644 skills/rfp-response/evidence/dogfood-output.json create mode 100644 skills/rfp-response/evidence/dogfood-output.stderr.txt create mode 100644 skills/rfp-response/evidence/dogfood-receipts-linux.tgz create mode 100644 skills/rfp-response/evidence/local-harness-receipts-linux.tgz create mode 100644 skills/rfp-response/evidence/local-harness-verification.json create mode 100644 skills/rfp-response/evidence/local-harness-verification.stderr.txt create mode 100644 skills/rfp-response/evidence/local-harness.json create mode 100644 skills/rfp-response/evidence/local-harness.stderr.txt create mode 100644 skills/rfp-response/evidence/runx-version.txt create mode 100644 skills/rfp-response/evidence/verification.json create mode 100644 skills/rfp-response/evidence/verification.stderr.txt create mode 100644 skills/rfp-response/fixtures/supported-questionnaire.json create mode 100644 skills/rfp-response/fixtures/unsupported-questionnaire.json create mode 100644 skills/rfp-response/run.mjs diff --git a/skills/rfp-response/SKILL.md b/skills/rfp-response/SKILL.md new file mode 100644 index 000000000..2c19e4cd1 --- /dev/null +++ b/skills/rfp-response/SKILL.md @@ -0,0 +1,63 @@ +--- +name: rfp-response +description: Draft cited RFP and security-questionnaire answers from a supplied knowledge pack, with gaps for unsupported questions. +source: + type: cli-tool + command: node + args: + - run.mjs + input_mode: stdin + cwd: . + timeout_seconds: 30 +inputs: + questionnaire: + type: json + required: true + description: Array of questionnaire prompts with id, question text, and optional section. + knowledge_pack: + type: json + required: true + description: Sources and claims that may be cited in answers. + objective: + type: string + required: false + description: Optional operator intent for the draft. +runx: + category: business-ops + input_resolution: + required: + - questionnaire + - knowledge_pack +--- + +# rfp-response + +Use this skill when an operator needs a reviewable RFP or security-questionnaire +draft that is grounded only in supplied company knowledge. The skill reads a +questionnaire and knowledge pack, drafts cited answers for supported questions, +and records unsupported questions as gaps instead of inventing certifications, +controls, metrics, or contractual claims. + +The skill is read-only over its inputs. It performs no network calls, sends no +responses, stores no secrets, and emits only a draft for human approval before it +leaves the organization. + +## Inputs + +- `questionnaire`: array of `{id, question, section}` records. +- `knowledge_pack`: object with a `sources` array. Each source may contain + `id`, `title`, `url`, and `claims`; each claim may contain `id`, `text`, and + optional `tags`. +- `objective`: optional operator intent. + +## Output + +The runner returns JSON with: + +- `answers` array: `{q, answer, citations, confidence}` for grounded answers. +- `gaps` array: unsupported questions with missing-evidence notes. +- `evidence_json` object: compact verification summary. +- `report` string: human-readable draft review notes. + +Every answer contains at least one citation. Questions without supporting +knowledge are placed in `gaps` and are not answered. diff --git a/skills/rfp-response/X.yaml b/skills/rfp-response/X.yaml new file mode 100644 index 000000000..2c014ede7 --- /dev/null +++ b/skills/rfp-response/X.yaml @@ -0,0 +1,104 @@ +skill: rfp-response +version: "0.1.0" + +catalog: + kind: skill + audience: public + visibility: public + role: canonical + +policy: + side_effects: none + network_during_run: denied + secrets_required: false + filesystem: + read: [] + write: [] + +harness: + cases: + - name: cited-security-questionnaire-answers + runner: default + inputs: + objective: "Draft grounded security questionnaire answers for a vendor review." + questionnaire: + - id: q1 + section: encryption + question: "Do you encrypt customer data at rest and in transit?" + - id: q2 + section: access + question: "How do you restrict production access?" + knowledge_pack: + sources: + - id: security-overview + title: "Acme Security Overview 2026" + url: "https://example.com/acme/security-overview" + claims: + - id: enc-1 + text: "Customer data is encrypted at rest with AES-256 and in transit with TLS 1.2 or newer." + tags: [encryption, data, transit, rest] + - id: access-1 + text: "Production access is limited to approved on-call engineers, requires MFA, and is reviewed quarterly." + tags: [access, production, mfa, review] + expect: + status: sealed + receipt: + schema: runx.receipt.v1 + state: sealed + disposition: closed + reason_code: process_closed + + - name: unsupported-certification-is-gap + runner: default + inputs: + objective: "Do not invent unsupported certifications." + questionnaire: + - id: q1 + section: compliance + question: "Are you ISO 27001 certified?" + knowledge_pack: + sources: + - id: security-overview + title: "Acme Security Overview 2026" + url: "https://example.com/acme/security-overview" + claims: + - id: access-1 + text: "Production access is limited to approved on-call engineers and requires MFA." + tags: [access, production, mfa] + expect: + status: sealed + receipt: + schema: runx.receipt.v1 + state: sealed + disposition: closed + reason_code: process_closed + +runners: + default: + default: true + type: cli-tool + command: node + input_mode: stdin + args: + - run.mjs + outputs: + answers: array + gaps: array + evidence_json: object + report: string + artifacts: + wrap_as: rfp_response_packet + packet: runx.business_ops.rfp_response.v1 + inputs: + questionnaire: + type: json + required: true + description: Questionnaire prompts to answer. + knowledge_pack: + type: json + required: true + description: Source-backed company knowledge pack. + objective: + type: string + required: false + description: Operator intent for the response draft. diff --git a/skills/rfp-response/evidence/dogfood-output.json b/skills/rfp-response/evidence/dogfood-output.json new file mode 100644 index 000000000..d1385c87f --- /dev/null +++ b/skills/rfp-response/evidence/dogfood-output.json @@ -0,0 +1,348 @@ +{ + "closure": { + "closed_at": "2026-06-23T05:10:42.304Z", + "disposition": "closed", + "reason_code": "process_closed", + "summary": "cli-tool default completed" + }, + "execution": { + "exit_code": 0, + "skill_claim": { + "answers": [ + { + "answer": "Customer data is encrypted at rest with AES-256 and in transit with TLS 1.2 or newer.", + "citations": [ + { + "claim_id": "enc-1", + "source_id": "security-overview", + "title": "Acme Security Overview 2026", + "url": "https://example.com/acme/security-overview" + } + ], + "confidence": "high", + "q": "q1", + "question": "Do you encrypt customer data at rest and in transit?", + "section": "encryption" + }, + { + "answer": "Production access is limited to approved on-call engineers, requires MFA, and is reviewed quarterly.", + "citations": [ + { + "claim_id": "access-1", + "source_id": "security-overview", + "title": "Acme Security Overview 2026", + "url": "https://example.com/acme/security-overview" + } + ], + "confidence": "medium", + "q": "q2", + "question": "How do you restrict production access?", + "section": "access" + } + ], + "evidence_json": { + "artifact": "rfp-response", + "knowledge_digest": "sha256:acbefb0d1a1a85c3b58fe86d7137f7de79a8eb5f0453116f32dcf6c43b0fc460", + "objective": "Draft grounded security questionnaire answers for a vendor review.", + "observations": { + "answered_count": 2, + "effect_emitted": false, + "gap_count": 0, + "network_used": false, + "read_only": true, + "refused_questions": [], + "sample_citations": [ + { + "claim_id": "enc-1", + "source_id": "security-overview", + "title": "Acme Security Overview 2026", + "url": "https://example.com/acme/security-overview" + }, + { + "claim_id": "access-1", + "source_id": "security-overview", + "title": "Acme Security Overview 2026", + "url": "https://example.com/acme/security-overview" + } + ] + }, + "questionnaire_digest": "sha256:f2428f3d99f2d48e9c64b554dd734057a7a9f591682f1cd77a5a11487eac82b7", + "schema": "frantic.delivery.evidence.v1" + }, + "gaps": [], + "report": "# rfp-response report\n\nAnswered questions: 2\nGaps: 0\nKnowledge sources: 1\n\n## Answers\n- q1: Customer data is encrypted at rest with AES-256 and in transit with TLS 1.2 or newer. Citations: security-overview/enc-1\n- q2: Production access is limited to approved on-call engineers, requires MFA, and is reviewed quarterly. Citations: security-overview/access-1\n\n## Gaps\n- none\n\nThe draft is read-only and requires human approval before external use." + }, + "stderr": "", + "stdout": "{\n \"answers\": [\n {\n \"q\": \"q1\",\n \"question\": \"Do you encrypt customer data at rest and in transit?\",\n \"section\": \"encryption\",\n \"answer\": \"Customer data is encrypted at rest with AES-256 and in transit with TLS 1.2 or newer.\",\n \"citations\": [\n {\n \"source_id\": \"security-overview\",\n \"claim_id\": \"enc-1\",\n \"title\": \"Acme Security Overview 2026\",\n \"url\": \"https://example.com/acme/security-overview\"\n }\n ],\n \"confidence\": \"high\"\n },\n {\n \"q\": \"q2\",\n \"question\": \"How do you restrict production access?\",\n \"section\": \"access\",\n \"answer\": \"Production access is limited to approved on-call engineers, requires MFA, and is reviewed quarterly.\",\n \"citations\": [\n {\n \"source_id\": \"security-overview\",\n \"claim_id\": \"access-1\",\n \"title\": \"Acme Security Overview 2026\",\n \"url\": \"https://example.com/acme/security-overview\"\n }\n ],\n \"confidence\": \"medium\"\n }\n ],\n \"gaps\": [],\n \"evidence_json\": {\n \"schema\": \"frantic.delivery.evidence.v1\",\n \"artifact\": \"rfp-response\",\n \"objective\": \"Draft grounded security questionnaire answers for a vendor review.\",\n \"knowledge_digest\": \"sha256:acbefb0d1a1a85c3b58fe86d7137f7de79a8eb5f0453116f32dcf6c43b0fc460\",\n \"questionnaire_digest\": \"sha256:f2428f3d99f2d48e9c64b554dd734057a7a9f591682f1cd77a5a11487eac82b7\",\n \"observations\": {\n \"answered_count\": 2,\n \"gap_count\": 0,\n \"sample_citations\": [\n {\n \"source_id\": \"security-overview\",\n \"claim_id\": \"enc-1\",\n \"title\": \"Acme Security Overview 2026\",\n \"url\": \"https://example.com/acme/security-overview\"\n },\n {\n \"source_id\": \"security-overview\",\n \"claim_id\": \"access-1\",\n \"title\": \"Acme Security Overview 2026\",\n \"url\": \"https://example.com/acme/security-overview\"\n }\n ],\n \"refused_questions\": [],\n \"read_only\": true,\n \"network_used\": false,\n \"effect_emitted\": false\n }\n },\n \"report\": \"# rfp-response report\\n\\nAnswered questions: 2\\nGaps: 0\\nKnowledge sources: 1\\n\\n## Answers\\n- q1: Customer data is encrypted at rest with AES-256 and in transit with TLS 1.2 or newer. Citations: security-overview/enc-1\\n- q2: Production access is limited to approved on-call engineers, requires MFA, and is reviewed quarterly. Citations: security-overview/access-1\\n\\n## Gaps\\n- none\\n\\nThe draft is read-only and requires human approval before external use.\"\n}\n", + "structured_output": { + "answers": [ + { + "answer": "Customer data is encrypted at rest with AES-256 and in transit with TLS 1.2 or newer.", + "citations": [ + { + "claim_id": "enc-1", + "source_id": "security-overview", + "title": "Acme Security Overview 2026", + "url": "https://example.com/acme/security-overview" + } + ], + "confidence": "high", + "q": "q1", + "question": "Do you encrypt customer data at rest and in transit?", + "section": "encryption" + }, + { + "answer": "Production access is limited to approved on-call engineers, requires MFA, and is reviewed quarterly.", + "citations": [ + { + "claim_id": "access-1", + "source_id": "security-overview", + "title": "Acme Security Overview 2026", + "url": "https://example.com/acme/security-overview" + } + ], + "confidence": "medium", + "q": "q2", + "question": "How do you restrict production access?", + "section": "access" + } + ], + "evidence_json": { + "artifact": "rfp-response", + "knowledge_digest": "sha256:acbefb0d1a1a85c3b58fe86d7137f7de79a8eb5f0453116f32dcf6c43b0fc460", + "objective": "Draft grounded security questionnaire answers for a vendor review.", + "observations": { + "answered_count": 2, + "effect_emitted": false, + "gap_count": 0, + "network_used": false, + "read_only": true, + "refused_questions": [], + "sample_citations": [ + { + "claim_id": "enc-1", + "source_id": "security-overview", + "title": "Acme Security Overview 2026", + "url": "https://example.com/acme/security-overview" + }, + { + "claim_id": "access-1", + "source_id": "security-overview", + "title": "Acme Security Overview 2026", + "url": "https://example.com/acme/security-overview" + } + ] + }, + "questionnaire_digest": "sha256:f2428f3d99f2d48e9c64b554dd734057a7a9f591682f1cd77a5a11487eac82b7", + "schema": "frantic.delivery.evidence.v1" + }, + "gaps": [], + "report": "# rfp-response report\n\nAnswered questions: 2\nGaps: 0\nKnowledge sources: 1\n\n## Answers\n- q1: Customer data is encrypted at rest with AES-256 and in transit with TLS 1.2 or newer. Citations: security-overview/enc-1\n- q2: Production access is limited to approved on-call engineers, requires MFA, and is reviewed quarterly. Citations: security-overview/access-1\n\n## Gaps\n- none\n\nThe draft is read-only and requires human approval before external use." + } + }, + "payload": { + "answers": [ + { + "answer": "Customer data is encrypted at rest with AES-256 and in transit with TLS 1.2 or newer.", + "citations": [ + { + "claim_id": "enc-1", + "source_id": "security-overview", + "title": "Acme Security Overview 2026", + "url": "https://example.com/acme/security-overview" + } + ], + "confidence": "high", + "q": "q1", + "question": "Do you encrypt customer data at rest and in transit?", + "section": "encryption" + }, + { + "answer": "Production access is limited to approved on-call engineers, requires MFA, and is reviewed quarterly.", + "citations": [ + { + "claim_id": "access-1", + "source_id": "security-overview", + "title": "Acme Security Overview 2026", + "url": "https://example.com/acme/security-overview" + } + ], + "confidence": "medium", + "q": "q2", + "question": "How do you restrict production access?", + "section": "access" + } + ], + "evidence_json": { + "artifact": "rfp-response", + "knowledge_digest": "sha256:acbefb0d1a1a85c3b58fe86d7137f7de79a8eb5f0453116f32dcf6c43b0fc460", + "objective": "Draft grounded security questionnaire answers for a vendor review.", + "observations": { + "answered_count": 2, + "effect_emitted": false, + "gap_count": 0, + "network_used": false, + "read_only": true, + "refused_questions": [], + "sample_citations": [ + { + "claim_id": "enc-1", + "source_id": "security-overview", + "title": "Acme Security Overview 2026", + "url": "https://example.com/acme/security-overview" + }, + { + "claim_id": "access-1", + "source_id": "security-overview", + "title": "Acme Security Overview 2026", + "url": "https://example.com/acme/security-overview" + } + ] + }, + "questionnaire_digest": "sha256:f2428f3d99f2d48e9c64b554dd734057a7a9f591682f1cd77a5a11487eac82b7", + "schema": "frantic.delivery.evidence.v1" + }, + "gaps": [], + "report": "# rfp-response report\n\nAnswered questions: 2\nGaps: 0\nKnowledge sources: 1\n\n## Answers\n- q1: Customer data is encrypted at rest with AES-256 and in transit with TLS 1.2 or newer. Citations: security-overview/enc-1\n- q2: Production access is limited to approved on-call engineers, requires MFA, and is reviewed quarterly. Citations: security-overview/access-1\n\n## Gaps\n- none\n\nThe draft is read-only and requires human approval before external use." + }, + "receipt": { + "acts": [ + { + "artifact_refs": [], + "closure": { + "closed_at": "2026-06-23T05:10:42.304Z", + "disposition": "closed", + "reason_code": "process_exit", + "summary": "cli-tool exited successfully" + }, + "criterion_bindings": [ + { + "criterion_id": "process_exit", + "evidence_refs": [], + "status": "verified", + "summary": "cli-tool exited successfully", + "verification_refs": [] + } + ], + "form": "observation", + "id": "act_default", + "intent": { + "constraints": [], + "derived_from": [], + "legitimacy": "Runtime graph execution was admitted by the local harness", + "purpose": "Run graph step default", + "success_criteria": [ + { + "criterion_id": "process_exit", + "required": true, + "statement": "cli-tool exits successfully" + } + ] + }, + "source_refs": [], + "summary": "Executed graph step default", + "target_refs": [] + } + ], + "authority": { + "actor_ref": { + "type": "principal", + "uri": "runx:principal:local_runtime" + }, + "attenuation": { + "parent_authority_ref": null, + "subset_proof": null + }, + "authority_proof_refs": [], + "enforcement": { + "profile_hash": "sha256:runtime-skeleton-enforcement", + "redaction_refs": [], + "setup_refs": [], + "teardown_refs": [] + }, + "grant_refs": [], + "scope_refs": [], + "terms": [] + }, + "canonicalization": "runx.receipt.c14n.v1", + "created_at": "2026-06-23T05:10:42.304Z", + "decisions": [ + { + "artifact_refs": [], + "choice": "open", + "closure": null, + "decision_id": "dec_default", + "inputs": { + "opportunity_refs": [], + "selection_ref": null, + "signal_refs": [], + "target_ref": null + }, + "justification": { + "evidence_refs": [], + "summary": "runtime graph planner selected this node" + }, + "proposed_intent": { + "constraints": [], + "derived_from": [], + "legitimacy": "Local graph execution requested this node", + "purpose": "Open runtime node default", + "success_criteria": [] + }, + "selected_act_id": "act_default", + "selected_harness_ref": null + } + ], + "digest": "sha256:2f1ce9d4c84c70e45f6b35cb9ada20286fc692c6dffaec2f07ca6467471eaf0a", + "id": "sha256:40987dbccf56a96603e2331e1591e2b3aaa94df07ea8cb8bd32c7c25623d7196", + "idempotency": { + "content_hash": "sha256:run_default_ce6bab504068-default-content", + "intent_key": "sha256:run_default_ce6bab504068-default-intent", + "trigger_fingerprint": "sha256:run_default_ce6bab504068-default-trigger" + }, + "issuer": { + "kid": "local:bountybar-frantic-runx-22-20260618192655", + "public_key_sha256": "sha256:afae74faf1b1b104b27d788bee2dd0982052af89a1ae30b3282f1a14b0707871", + "type": "hosted" + }, + "lineage": { + "children": [], + "sync": [] + }, + "schema": "runx.receipt.v1", + "seal": { + "closed_at": "2026-06-23T05:10:42.304Z", + "criteria": [ + { + "criterion_id": "process_exit", + "evidence_refs": [], + "status": "verified", + "summary": "cli-tool exited successfully", + "verification_refs": [] + } + ], + "disposition": "closed", + "last_observed_at": "2026-06-23T05:10:42.304Z", + "reason_code": "process_closed", + "summary": "cli-tool default completed" + }, + "signals": [], + "signature": { + "alg": "Ed25519", + "value": "base64:PTGPm-0YrxF9S39qgeUJtXKYZDlRDFQncD3hSJPdq6kKtXCd82kq8jTbeQueyTAQehwfWEjuv8EaUviRbD--Dg" + }, + "subject": { + "commitments": [], + "kind": "skill", + "ref": { + "type": "harness", + "uri": "hrn_run_default_ce6bab504068_default" + } + } + }, + "receipt_id": "sha256:40987dbccf56a96603e2331e1591e2b3aaa94df07ea8cb8bd32c7c25623d7196", + "run_id": "run_default_ce6bab504068", + "schema": "runx.skill_run.v1", + "skill_name": "rfp-response", + "status": "sealed" +} diff --git a/skills/rfp-response/evidence/dogfood-output.stderr.txt b/skills/rfp-response/evidence/dogfood-output.stderr.txt new file mode 100644 index 000000000..e69de29bb diff --git a/skills/rfp-response/evidence/dogfood-receipts-linux.tgz b/skills/rfp-response/evidence/dogfood-receipts-linux.tgz new file mode 100644 index 0000000000000000000000000000000000000000..e0e7d179fd6372f2d1f4e7304a7ca7cf4ef87d60 GIT binary patch literal 1501 zcmV<31tR(%iwFP!000001MOFBZ`(Ey&QB5aIZCN_*`GEn>3}Z4+BC)54ue5aC!2{( zDkSB`3-aH0l;pQGX&kgoQB3C#GGBD}+}(30QZ?e*Q)TTb(6tmAyh2V(DGQunz-yyl z9DJ=1lr)a*(@$g4KmB&Tmjgcz{3P;&I0z1ipO7#-aN@7FyoWT}P~|uW8uBmhdu;tD zm7^C&FMc_dVtUHO<#)1S6P!fRD&KdXHr+d1AU@8J1LyQR;n|T@{*{#GOZy&M|4BtX zUjKSVgE$#SWR#^v&R7{Ibd+F;LJ)>N`0>bxAP*^}qo^oJ3N&MRmKR~bQig8^VUhZy zT?{@eN|U&w?O{pZTL8 ziDP`NZt{w=$t5f&o!^@P(2_zLm9+G8{E;XR(jv{W93UtP3{F7efR@>a`V>Nvhd~yU zKJ}xVq$JH!-@QF_HJ=J<8U+?It){5`qzK~JAEE69ts3h?PBkRa`1Sekujd~5psrtz z-iD*ADZG1S-v9C8<8gI%{PK-p$KmYltJlRlzpM*Vr&_tYFM11(dX@%!EOb(>x{-NiwgW z^tzW&nNfT?1vM$Tz(=ic;R$N`w=Iuk2V+L{>aDQ>stWmOv*mVGc2&Ql0LC>cvBR77Xwvoz9IexX*_lbsY|JrU!jfFnjZM@|uW;Ke zRZ}qA0g-hrm1#sDr#0LP)-J5$gwd#_#?IK6fDKTi>=YXR6OB84WE>$2a5e}lm~xz_ zw(8tdn|KGaUC$i22G&?Rj)JQOY*Td1jO$i`YtzLT5_ZBckDxg1&>{1+QIz*|w6Rir zfw)Q~=RH9?4{R4_rVE<=vw^f;?`vW^CKvdzp|CBaO6s<)c7~`zI~Lb^i)Ax2UC!@8jWnCvL?emSqJwwn-j|KDM)Vjl zru9RqINR}NlZ;PPJG8)(w?5@dbPJreUY$(`xhFL@Za-M@6baMrfotBz+~9Y$D=mx! z_l%U4W7o9PYb!A<%eI8B8jf}3j*V*IcHf+@({$3hg5d9s!3JfH-4eUE-V=O-8{Gx& zDS7+#{w&3Z{c1;@?SfiE+i@Hb?s#rJ)v{4LDmO*D>UVc(vqday6&z2Le-3_(YHYjhw!PpW>8Uo8u4wi- z*FBBV&p-;~cEttIX`5g+<5hv5xL(OpuHWof2HXg zUn1LMqo8y6c3N9*?|nbTuJNOjHpn1@3^K?dgA6jrAcG7t$RL9Z@&x%0HSylI04M+e Du;}qO literal 0 HcmV?d00001 diff --git a/skills/rfp-response/evidence/local-harness-receipts-linux.tgz b/skills/rfp-response/evidence/local-harness-receipts-linux.tgz new file mode 100644 index 0000000000000000000000000000000000000000..23fdd8d001fbf3e8e9ac6ee6e377da45117bcd92 GIT binary patch literal 1830 zcmV+>2if=^iwFP!000001MON{bKABO_D|vH*>V8hsi%`PansaETiYjX-8rKHK|n%G zfh+*pRy_XiU69nxQEIt%oOBL8KhOlgz3&3pk!s}CQ1N=Gn64|S*>FmfWLm=jWui9v z+1^8e07(?tCr%>NKXE(WV-H6@jzjE6IN3uuMls&=q6c%{0gX09dETC8`QNU)YyMw~ zgJ%cN{&Q5x$&rxfUxR`DDn<+|#>4YB0JUn0d`$-L%rc0cOry*~<#3jPk0HW}Xu@rDRED1T`IEOzJ=6+HnX__)gdRE#o_41luy2!$dB*F zS0^#|#qaXtVR|ki>7TrL{r>n^oxT6%6>u&?y|059>%}Fh{XH( zTjT!}zl_COc9NRtM8~J!J-1R6V#2gpX@;U4hjC6R!&&6#A&)srIROPol7wl5!Xins zFaY-i8Rh|aJ3qFSzQ?>>D;O&B>Zcv8CP7u=Hr5K(v)UQNyfthk%C5a z*bff7kARp_VlrWB%!PzUtzhCFWcsgd995kdQ=+H$Akcr-`m4!5Flwwy=R&sGa4yOc zXe-9o!>+5DFy1I(-<2GHj?ZGy(x=sICd>@D>A~oa|G@}p%(PO%v}PpKRBF7*%9?|U znv_dsHke1t;ZYm&mb(!%W|>TE&|4}k4^WC$HCuaMvK-fN$l>cV1`N^kIe0y&iL&Ng zt#2ihO6JPCAHu zZ4?oGI9gjNaRG91Rn7VU?KH4eoSM#P_MeqV%lSSh)@||uHe11=vM(Y^H?tX0^Dc;6 z1v~NUl1Ryvw;;A5JG+2tBk3xHZ6cMGZp&)Nh$!G=UUd*~Azg@9?- zuq)Bp+`zutr50F13{6#)o}JTPPmP0F=4}f7*$Bv^!N{nF-R$b~rJG*0s(|oYZLpFu zhiVDcTkj}*0}BTiu!f6v_x{Ai`~7SeI_n9w6m3IskZ?nDtEsLUwLx-~w2OLoJ8aeh z3rdB66S5ZliNsE{vcjPTE;eIogY#46b`x*ECwIru=%!VJLG8bm$U^A+r z?6%8x5(k2wXfy7TW|wo_{UZ7af&yZ@6q1oi>tH$+WdU1UPh>7>w}E`^Gy0c=>;Jg^ z&u;gBxZ>b~1`Lk;yx>WS84Y4a(=fw+64Qk90O2f7Bbw8KW?>pqnr0ZGl&3LVid_Ha zTf|fN{~z>!P=H+j=P9sr|L39Uzf1oo4l~#PS@eJ2)>i@gIpO(lb9Fp>`$A9NHD;{8 z|24tShsjZOmimY0=Qpp9UTgK-kJyi=XK~hCUL=R_>$?0^y*fV4&M$`rJ&WT1{`jVR z`9pgC@|SJ>pQy+(pK|U;Daf7$L7HZ1%nKC6oS}?lIU#-);h57Pi8zZfj(Cx0LC8>) zq2M3%e^{K8JVGIg(}(nbwvoA4|7RP4FVX*5#F{O(j#9Y+he07Gxm5?+t}XuetNUN zUAIU0fy5Tw9_3e8JOB0qD&p4;NCyW82L}fS2L}fS2L}fS2L}fS2L}fS2L}fS2L}fS U2L}fS2Zx>T7k0r{v;a^50N-GpN&o-= literal 0 HcmV?d00001 diff --git a/skills/rfp-response/evidence/local-harness-verification.json b/skills/rfp-response/evidence/local-harness-verification.json new file mode 100644 index 000000000..a18290c5e --- /dev/null +++ b/skills/rfp-response/evidence/local-harness-verification.json @@ -0,0 +1,22 @@ +{ + "receipt_dir": "/tmp/runx-rfp-response-harness-receipts", + "signature_mode": "production", + "trees": [ + { + "root_receipt_id": "sha256:0981dc3e02dfdf781ec36ec8491276c7ff3019685cbcdc9484cc891008f86a1a", + "receipt_count": 1, + "parent_missing": null, + "valid": true, + "findings": [] + }, + { + "root_receipt_id": "sha256:bf4f0f576eaad7228c7b23e8d73d0737f5b03d9b1939aca25141dff76af52620", + "receipt_count": 1, + "parent_missing": null, + "valid": true, + "findings": [] + } + ], + "unreadable_files": [], + "valid": true +} diff --git a/skills/rfp-response/evidence/local-harness-verification.stderr.txt b/skills/rfp-response/evidence/local-harness-verification.stderr.txt new file mode 100644 index 000000000..e69de29bb diff --git a/skills/rfp-response/evidence/local-harness.json b/skills/rfp-response/evidence/local-harness.json new file mode 100644 index 000000000..9bceecca0 --- /dev/null +++ b/skills/rfp-response/evidence/local-harness.json @@ -0,0 +1,15 @@ +{ + "status": "passed", + "case_count": 2, + "assertion_error_count": 0, + "assertion_errors": [], + "case_names": [ + "cited-security-questionnaire-answers", + "unsupported-certification-is-gap" + ], + "receipt_ids": [ + "sha256:0981dc3e02dfdf781ec36ec8491276c7ff3019685cbcdc9484cc891008f86a1a", + "sha256:bf4f0f576eaad7228c7b23e8d73d0737f5b03d9b1939aca25141dff76af52620" + ], + "graph_case_count": 0 +} diff --git a/skills/rfp-response/evidence/local-harness.stderr.txt b/skills/rfp-response/evidence/local-harness.stderr.txt new file mode 100644 index 000000000..e69de29bb diff --git a/skills/rfp-response/evidence/runx-version.txt b/skills/rfp-response/evidence/runx-version.txt new file mode 100644 index 000000000..6ff8172cb --- /dev/null +++ b/skills/rfp-response/evidence/runx-version.txt @@ -0,0 +1 @@ +runx-cli 0.6.13 diff --git a/skills/rfp-response/evidence/verification.json b/skills/rfp-response/evidence/verification.json new file mode 100644 index 000000000..29515077f --- /dev/null +++ b/skills/rfp-response/evidence/verification.json @@ -0,0 +1,15 @@ +{ + "receipt_dir": "/tmp/runx-rfp-response-dogfood-receipts", + "signature_mode": "production", + "trees": [ + { + "root_receipt_id": "sha256:40987dbccf56a96603e2331e1591e2b3aaa94df07ea8cb8bd32c7c25623d7196", + "receipt_count": 1, + "parent_missing": null, + "valid": true, + "findings": [] + } + ], + "unreadable_files": [], + "valid": true +} diff --git a/skills/rfp-response/evidence/verification.stderr.txt b/skills/rfp-response/evidence/verification.stderr.txt new file mode 100644 index 000000000..e69de29bb diff --git a/skills/rfp-response/fixtures/supported-questionnaire.json b/skills/rfp-response/fixtures/supported-questionnaire.json new file mode 100644 index 000000000..b90bb8f03 --- /dev/null +++ b/skills/rfp-response/fixtures/supported-questionnaire.json @@ -0,0 +1,36 @@ +{ + "objective": "Draft grounded security questionnaire answers for a vendor review.", + "questionnaire": [ + { + "id": "q1", + "section": "encryption", + "question": "Do you encrypt customer data at rest and in transit?" + }, + { + "id": "q2", + "section": "access", + "question": "How do you restrict production access?" + } + ], + "knowledge_pack": { + "sources": [ + { + "id": "security-overview", + "title": "Acme Security Overview 2026", + "url": "https://example.com/acme/security-overview", + "claims": [ + { + "id": "enc-1", + "text": "Customer data is encrypted at rest with AES-256 and in transit with TLS 1.2 or newer.", + "tags": ["encryption", "data", "transit", "rest"] + }, + { + "id": "access-1", + "text": "Production access is limited to approved on-call engineers, requires MFA, and is reviewed quarterly.", + "tags": ["access", "production", "mfa", "review"] + } + ] + } + ] + } +} diff --git a/skills/rfp-response/fixtures/unsupported-questionnaire.json b/skills/rfp-response/fixtures/unsupported-questionnaire.json new file mode 100644 index 000000000..8471b1cde --- /dev/null +++ b/skills/rfp-response/fixtures/unsupported-questionnaire.json @@ -0,0 +1,26 @@ +{ + "objective": "Do not invent unsupported certifications.", + "questionnaire": [ + { + "id": "q1", + "section": "compliance", + "question": "Are you ISO 27001 certified?" + } + ], + "knowledge_pack": { + "sources": [ + { + "id": "security-overview", + "title": "Acme Security Overview 2026", + "url": "https://example.com/acme/security-overview", + "claims": [ + { + "id": "access-1", + "text": "Production access is limited to approved on-call engineers and requires MFA.", + "tags": ["access", "production", "mfa"] + } + ] + } + ] + } +} diff --git a/skills/rfp-response/run.mjs b/skills/rfp-response/run.mjs new file mode 100644 index 000000000..ec8b8d939 --- /dev/null +++ b/skills/rfp-response/run.mjs @@ -0,0 +1,192 @@ +import fs from "node:fs"; +import crypto from "node:crypto"; + +const inputs = readInputs(); +const questionnaire = requireArray(inputs.questionnaire, "questionnaire"); +const knowledgePack = requireObject(inputs.knowledge_pack, "knowledge_pack"); +const objective = stringValue(inputs.objective) || "Draft grounded RFP responses."; + +const sources = normalizeSources(knowledgePack); +const answers = []; +const gaps = []; + +for (const rawQuestion of questionnaire) { + const item = normalizeQuestion(rawQuestion); + const matches = rankClaims(item, sources); + if (matches.length === 0) { + gaps.push({ + q: item.id, + question: item.question, + section: item.section, + reason: "No supplied knowledge-pack claim supports this answer.", + needed_evidence: "Add a source claim that directly addresses the requested fact before answering.", + }); + continue; + } + + const top = matches.slice(0, 3); + answers.push({ + q: item.id, + question: item.question, + section: item.section, + answer: top.map((match) => match.claim.text).join(" "), + citations: top.map((match) => ({ + source_id: match.source.id, + claim_id: match.claim.id, + title: match.source.title, + url: match.source.url || null, + })), + confidence: confidenceFromScore(top[0].score), + }); +} + +const evidenceJson = { + schema: "frantic.delivery.evidence.v1", + artifact: "rfp-response", + objective, + knowledge_digest: sha256Json(knowledgePack), + questionnaire_digest: sha256Json(questionnaire), + observations: { + answered_count: answers.length, + gap_count: gaps.length, + sample_citations: answers.flatMap((answer) => answer.citations).slice(0, 5), + refused_questions: gaps.map((gap) => gap.q), + read_only: true, + network_used: false, + effect_emitted: false, + }, +}; + +const report = renderReport(answers, gaps, sources); + +process.stdout.write(`${JSON.stringify({ answers, gaps, evidence_json: evidenceJson, report }, null, 2)}\n`); + +function normalizeQuestion(value) { + if (!isObject(value)) throw new Error("questionnaire entries must be objects"); + const id = stringValue(value.id) || `q${answers.length + gaps.length + 1}`; + const question = stringValue(value.question); + if (!question) throw new Error(`questionnaire.${id}.question is required`); + return { + id, + question, + section: stringValue(value.section) || "general", + tokens: tokenize(question), + }; +} + +function normalizeSources(pack) { + const rawSources = requireArray(pack.sources, "knowledge_pack.sources"); + const normalized = rawSources.map((source, sourceIndex) => { + if (!isObject(source)) throw new Error(`knowledge_pack.sources[${sourceIndex}] must be an object`); + const id = stringValue(source.id) || `source-${sourceIndex + 1}`; + const claims = requireArray(source.claims, `knowledge_pack.sources.${id}.claims`).map((claim, claimIndex) => { + if (!isObject(claim)) throw new Error(`claim ${claimIndex + 1} in ${id} must be an object`); + const text = stringValue(claim.text); + if (!text) throw new Error(`claim ${claimIndex + 1} in ${id} requires text`); + const tags = arrayValue(claim.tags).map(String); + return { + id: stringValue(claim.id) || `${id}-claim-${claimIndex + 1}`, + text, + tags, + tokens: new Set([...tokenize(text), ...tags.flatMap(tokenize)]), + }; + }); + return { + id, + title: stringValue(source.title) || id, + url: stringValue(source.url), + claims, + }; + }); + if (normalized.length === 0) throw new Error("knowledge_pack.sources must not be empty"); + return normalized; +} + +function rankClaims(question, normalizedSources) { + const results = []; + for (const source of normalizedSources) { + for (const claim of source.claims) { + const overlap = question.tokens.filter((token) => claim.tokens.has(token)); + const exactSectionBoost = claim.tokens.has(question.section.toLowerCase()) ? 2 : 0; + const score = overlap.length + exactSectionBoost; + if (score >= 2) results.push({ source, claim, score }); + } + } + return results.sort((a, b) => b.score - a.score || a.claim.id.localeCompare(b.claim.id)); +} + +function confidenceFromScore(score) { + if (score >= 5) return "high"; + if (score >= 3) return "medium"; + return "low"; +} + +function renderReport(answerRows, gapRows, normalizedSources) { + const lines = [ + "# rfp-response report", + "", + `Answered questions: ${answerRows.length}`, + `Gaps: ${gapRows.length}`, + `Knowledge sources: ${normalizedSources.length}`, + "", + "## Answers", + ...answerRows.map((answer) => `- ${answer.q}: ${answer.answer} Citations: ${answer.citations.map((c) => `${c.source_id}/${c.claim_id}`).join(", ")}`), + "", + "## Gaps", + ...(gapRows.length ? gapRows.map((gap) => `- ${gap.q}: ${gap.reason}`) : ["- none"]), + "", + "The draft is read-only and requires human approval before external use.", + ]; + return lines.join("\n"); +} + +function readInputs() { + if (process.env.RUNX_INPUTS_PATH) return JSON.parse(fs.readFileSync(process.env.RUNX_INPUTS_PATH, "utf8")); + if (process.env.RUNX_INPUTS_JSON) return JSON.parse(process.env.RUNX_INPUTS_JSON); + if (!process.stdin.isTTY) { + const raw = fs.readFileSync(0, "utf8").trim(); + if (raw) return JSON.parse(raw); + } + return {}; +} + +function requireObject(value, field) { + if (!isObject(value)) throw new Error(`${field} must be an object`); + return value; +} + +function requireArray(value, field) { + if (!Array.isArray(value)) throw new Error(`${field} must be an array`); + return value; +} + +function isObject(value) { + return Boolean(value) && typeof value === "object" && !Array.isArray(value); +} + +function arrayValue(value) { + return Array.isArray(value) ? value : []; +} + +function stringValue(value) { + return typeof value === "string" && value.trim().length > 0 ? value.trim() : null; +} + +function tokenize(text) { + const stop = new Set(["a", "an", "and", "are", "at", "by", "do", "does", "for", "how", "in", "is", "of", "or", "the", "to", "with", "you", "your"]); + return String(text) + .toLowerCase() + .replace(/[^a-z0-9]+/g, " ") + .split(/\s+/) + .filter((token) => token.length > 2 && !stop.has(token)); +} + +function sha256Json(value) { + return `sha256:${crypto.createHash("sha256").update(JSON.stringify(sortJson(value))).digest("hex")}`; +} + +function sortJson(value) { + if (Array.isArray(value)) return value.map(sortJson); + if (isObject(value)) return Object.fromEntries(Object.keys(value).sort().map((key) => [key, sortJson(value[key])])); + return value; +} From b33992ef29c0ec68c06529df5ff74a8b5860cdd2 Mon Sep 17 00:00:00 2001 From: LubuSeb <187313664+LubuSeb@users.noreply.github.com> Date: Tue, 23 Jun 2026 07:12:48 +0200 Subject: [PATCH 2/3] Add RFP response fail-closed harness case --- skills/rfp-response/X.yaml | 13 +++++++++++++ .../rfp-response/evidence/dogfood-output.json | 18 +++++++++--------- .../evidence/dogfood-receipts-linux.tgz | Bin 1501 -> 1498 bytes .../evidence/local-harness-receipts-linux.tgz | Bin 1830 -> 2425 bytes .../evidence/local-harness-verification.json | 11 +++++++++-- .../rfp-response/evidence/local-harness.json | 10 ++++++---- .../evidence/registry-publish.json | 7 +++++++ .../evidence/registry-publish.stderr.txt | 0 .../rfp-response/evidence/verification.json | 2 +- 9 files changed, 45 insertions(+), 16 deletions(-) create mode 100644 skills/rfp-response/evidence/registry-publish.json create mode 100644 skills/rfp-response/evidence/registry-publish.stderr.txt diff --git a/skills/rfp-response/X.yaml b/skills/rfp-response/X.yaml index 2c014ede7..7ed900576 100644 --- a/skills/rfp-response/X.yaml +++ b/skills/rfp-response/X.yaml @@ -73,6 +73,19 @@ harness: disposition: closed reason_code: process_closed + - name: missing-knowledge-pack-fails-closed + runner: default + inputs: + objective: "Fail closed when grounding sources are absent." + questionnaire: + - id: q1 + section: compliance + question: "Are you ISO 27001 certified?" + knowledge_pack: + sources: [] + expect: + status: failure + runners: default: default: true diff --git a/skills/rfp-response/evidence/dogfood-output.json b/skills/rfp-response/evidence/dogfood-output.json index d1385c87f..6b3af3cc6 100644 --- a/skills/rfp-response/evidence/dogfood-output.json +++ b/skills/rfp-response/evidence/dogfood-output.json @@ -1,6 +1,6 @@ { "closure": { - "closed_at": "2026-06-23T05:10:42.304Z", + "closed_at": "2026-06-23T05:12:41.192Z", "disposition": "closed", "reason_code": "process_closed", "summary": "cli-tool default completed" @@ -210,7 +210,7 @@ { "artifact_refs": [], "closure": { - "closed_at": "2026-06-23T05:10:42.304Z", + "closed_at": "2026-06-23T05:12:41.192Z", "disposition": "closed", "reason_code": "process_exit", "summary": "cli-tool exited successfully" @@ -265,7 +265,7 @@ "terms": [] }, "canonicalization": "runx.receipt.c14n.v1", - "created_at": "2026-06-23T05:10:42.304Z", + "created_at": "2026-06-23T05:12:41.192Z", "decisions": [ { "artifact_refs": [], @@ -293,8 +293,8 @@ "selected_harness_ref": null } ], - "digest": "sha256:2f1ce9d4c84c70e45f6b35cb9ada20286fc692c6dffaec2f07ca6467471eaf0a", - "id": "sha256:40987dbccf56a96603e2331e1591e2b3aaa94df07ea8cb8bd32c7c25623d7196", + "digest": "sha256:b2d0368ee5469619477aa4f85f7c1153218a8a017bfcf07373daed59313861bb", + "id": "sha256:6303ab1d488d60b75465c3dd2d7886eb5c15ec78739388a53a21eb1383d3b7ae", "idempotency": { "content_hash": "sha256:run_default_ce6bab504068-default-content", "intent_key": "sha256:run_default_ce6bab504068-default-intent", @@ -311,7 +311,7 @@ }, "schema": "runx.receipt.v1", "seal": { - "closed_at": "2026-06-23T05:10:42.304Z", + "closed_at": "2026-06-23T05:12:41.192Z", "criteria": [ { "criterion_id": "process_exit", @@ -322,14 +322,14 @@ } ], "disposition": "closed", - "last_observed_at": "2026-06-23T05:10:42.304Z", + "last_observed_at": "2026-06-23T05:12:41.192Z", "reason_code": "process_closed", "summary": "cli-tool default completed" }, "signals": [], "signature": { "alg": "Ed25519", - "value": "base64:PTGPm-0YrxF9S39qgeUJtXKYZDlRDFQncD3hSJPdq6kKtXCd82kq8jTbeQueyTAQehwfWEjuv8EaUviRbD--Dg" + "value": "base64:IAGF8Uzho2YNmOKlreOks-GR_T02Z0BrfO-TT2JmBGLkdRDzsv84dcv4Rn5E4atY-QO19vIV9AusU20EIT3ICQ" }, "subject": { "commitments": [], @@ -340,7 +340,7 @@ } } }, - "receipt_id": "sha256:40987dbccf56a96603e2331e1591e2b3aaa94df07ea8cb8bd32c7c25623d7196", + "receipt_id": "sha256:6303ab1d488d60b75465c3dd2d7886eb5c15ec78739388a53a21eb1383d3b7ae", "run_id": "run_default_ce6bab504068", "schema": "runx.skill_run.v1", "skill_name": "rfp-response", diff --git a/skills/rfp-response/evidence/dogfood-receipts-linux.tgz b/skills/rfp-response/evidence/dogfood-receipts-linux.tgz index e0e7d179fd6372f2d1f4e7304a7ca7cf4ef87d60..3cf12aa9a29f0cea39e98d848588fed03be39648 100644 GIT binary patch delta 1494 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 literal 1830 zcmV+>2if=^iwFP!000001MON{bKABO_D|vH*>V8hsi%`PansaETiYjX-8rKHK|n%G zfh+*pRy_XiU69nxQEIt%oOBL8KhOlgz3&3pk!s}CQ1N=Gn64|S*>FmfWLm=jWui9v z+1^8e07(?tCr%>NKXE(WV-H6@jzjE6IN3uuMls&=q6c%{0gX09dETC8`QNU)YyMw~ zgJ%cN{&Q5x$&rxfUxR`DDn<+|#>4YB0JUn0d`$-L%rc0cOry*~<#3jPk0HW}Xu@rDRED1T`IEOzJ=6+HnX__)gdRE#o_41luy2!$dB*F zS0^#|#qaXtVR|ki>7TrL{r>n^oxT6%6>u&?y|059>%}Fh{XH( zTjT!}zl_COc9NRtM8~J!J-1R6V#2gpX@;U4hjC6R!&&6#A&)srIROPol7wl5!Xins zFaY-i8Rh|aJ3qFSzQ?>>D;O&B>Zcv8CP7u=Hr5K(v)UQNyfthk%C5a z*bff7kARp_VlrWB%!PzUtzhCFWcsgd995kdQ=+H$Akcr-`m4!5Flwwy=R&sGa4yOc zXe-9o!>+5DFy1I(-<2GHj?ZGy(x=sICd>@D>A~oa|G@}p%(PO%v}PpKRBF7*%9?|U znv_dsHke1t;ZYm&mb(!%W|>TE&|4}k4^WC$HCuaMvK-fN$l>cV1`N^kIe0y&iL&Ng zt#2ihO6JPCAHu zZ4?oGI9gjNaRG91Rn7VU?KH4eoSM#P_MeqV%lSSh)@||uHe11=vM(Y^H?tX0^Dc;6 z1v~NUl1Ryvw;;A5JG+2tBk3xHZ6cMGZp&)Nh$!G=UUd*~Azg@9?- zuq)Bp+`zutr50F13{6#)o}JTPPmP0F=4}f7*$Bv^!N{nF-R$b~rJG*0s(|oYZLpFu zhiVDcTkj}*0}BTiu!f6v_x{Ai`~7SeI_n9w6m3IskZ?nDtEsLUwLx-~w2OLoJ8aeh z3rdB66S5ZliNsE{vcjPTE;eIogY#46b`x*ECwIru=%!VJLG8bm$U^A+r z?6%8x5(k2wXfy7TW|wo_{UZ7af&yZ@6q1oi>tH$+WdU1UPh>7>w}E`^Gy0c=>;Jg^ z&u;gBxZ>b~1`Lk;yx>WS84Y4a(=fw+64Qk90O2f7Bbw8KW?>pqnr0ZGl&3LVid_Ha zTf|fN{~z>!P=H+j=P9sr|L39Uzf1oo4l~#PS@eJ2)>i@gIpO(lb9Fp>`$A9NHD;{8 z|24tShsjZOmimY0=Qpp9UTgK-kJyi=XK~hCUL=R_>$?0^y*fV4&M$`rJ&WT1{`jVR z`9pgC@|SJ>pQy+(pK|U;Daf7$L7HZ1%nKC6oS}?lIU#-);h57Pi8zZfj(Cx0LC8>) zq2M3%e^{K8JVGIg(}(nbwvoA4|7RP4FVX*5#F{O(j#9Y+he07Gxm5?+t}XuetNUN zUAIU0fy5Tw9_3e8JOB0qD&p4;NCyW82L}fS2L}fS2L}fS2L}fS2L}fS2L}fS2L}fS U2L}fS2Zx>T7k0r{v;a^50N-GpN&o-= diff --git a/skills/rfp-response/evidence/local-harness-verification.json b/skills/rfp-response/evidence/local-harness-verification.json index a18290c5e..477eb7505 100644 --- a/skills/rfp-response/evidence/local-harness-verification.json +++ b/skills/rfp-response/evidence/local-harness-verification.json @@ -3,14 +3,21 @@ "signature_mode": "production", "trees": [ { - "root_receipt_id": "sha256:0981dc3e02dfdf781ec36ec8491276c7ff3019685cbcdc9484cc891008f86a1a", + "root_receipt_id": "sha256:25e83c91fbc6518568cbceea6e1eba4008c66a6aa948c7be3020b0b810278d1b", "receipt_count": 1, "parent_missing": null, "valid": true, "findings": [] }, { - "root_receipt_id": "sha256:bf4f0f576eaad7228c7b23e8d73d0737f5b03d9b1939aca25141dff76af52620", + "root_receipt_id": "sha256:890534895c208cd19908179cc33b077b3a793df109020aad35c7ee457cbe7e1a", + "receipt_count": 1, + "parent_missing": null, + "valid": true, + "findings": [] + }, + { + "root_receipt_id": "sha256:ce19f957d334d3ed8b4f5b5a25b44d13198d0928f442adcfc8ebcc3cd24ded05", "receipt_count": 1, "parent_missing": null, "valid": true, diff --git a/skills/rfp-response/evidence/local-harness.json b/skills/rfp-response/evidence/local-harness.json index 9bceecca0..77889d620 100644 --- a/skills/rfp-response/evidence/local-harness.json +++ b/skills/rfp-response/evidence/local-harness.json @@ -1,15 +1,17 @@ { "status": "passed", - "case_count": 2, + "case_count": 3, "assertion_error_count": 0, "assertion_errors": [], "case_names": [ "cited-security-questionnaire-answers", - "unsupported-certification-is-gap" + "unsupported-certification-is-gap", + "missing-knowledge-pack-fails-closed" ], "receipt_ids": [ - "sha256:0981dc3e02dfdf781ec36ec8491276c7ff3019685cbcdc9484cc891008f86a1a", - "sha256:bf4f0f576eaad7228c7b23e8d73d0737f5b03d9b1939aca25141dff76af52620" + "sha256:25e83c91fbc6518568cbceea6e1eba4008c66a6aa948c7be3020b0b810278d1b", + "sha256:890534895c208cd19908179cc33b077b3a793df109020aad35c7ee457cbe7e1a", + "sha256:ce19f957d334d3ed8b4f5b5a25b44d13198d0928f442adcfc8ebcc3cd24ded05" ], "graph_case_count": 0 } diff --git a/skills/rfp-response/evidence/registry-publish.json b/skills/rfp-response/evidence/registry-publish.json new file mode 100644 index 000000000..fffb3ab60 --- /dev/null +++ b/skills/rfp-response/evidence/registry-publish.json @@ -0,0 +1,7 @@ +{ + "status": "failure", + "error": { + "message": "remote registry publish failed [skill_harness_incomplete]: Publish harness must include a stop/error case such as needs_agent, policy_denied, failure, or escalated.", + "code": "registry_error" + } +} diff --git a/skills/rfp-response/evidence/registry-publish.stderr.txt b/skills/rfp-response/evidence/registry-publish.stderr.txt new file mode 100644 index 000000000..e69de29bb diff --git a/skills/rfp-response/evidence/verification.json b/skills/rfp-response/evidence/verification.json index 29515077f..1b996e658 100644 --- a/skills/rfp-response/evidence/verification.json +++ b/skills/rfp-response/evidence/verification.json @@ -3,7 +3,7 @@ "signature_mode": "production", "trees": [ { - "root_receipt_id": "sha256:40987dbccf56a96603e2331e1591e2b3aaa94df07ea8cb8bd32c7c25623d7196", + "root_receipt_id": "sha256:6303ab1d488d60b75465c3dd2d7886eb5c15ec78739388a53a21eb1383d3b7ae", "receipt_count": 1, "parent_missing": null, "valid": true, From 402ee2119c88958613d07789d93e52a1df06ffee Mon Sep 17 00:00:00 2001 From: LubuSeb <187313664+LubuSeb@users.noreply.github.com> Date: Tue, 23 Jun 2026 07:13:54 +0200 Subject: [PATCH 3/3] Add hosted RFP response evidence --- .../rfp-response/evidence/clean-install.json | 43 +++ .../evidence/clean-install.stderr.txt | 0 skills/rfp-response/evidence/evidence.json | 132 +++++++ .../evidence/hosted-dogfood-output.json | 359 ++++++++++++++++++ .../evidence/hosted-dogfood-output.stderr.txt | 0 .../hosted-dogfood-receipts-linux.tgz | Bin 0 -> 1504 bytes .../hosted-harness-receipts-linux.tgz | Bin 0 -> 2436 bytes .../evidence/hosted-harness-verification.json | 29 ++ .../hosted-harness-verification.stderr.txt | 0 .../rfp-response/evidence/hosted-harness.json | 17 + .../evidence/hosted-harness.stderr.txt | 0 .../evidence/hosted-verification.json | 15 + .../evidence/hosted-verification.stderr.txt | 0 .../evidence/registry-publish.json | 21 +- .../rfp-response/evidence/registry-read.json | 50 +++ .../evidence/registry-read.stderr.txt | 0 skills/rfp-response/evidence/report.md | 24 ++ 17 files changed, 686 insertions(+), 4 deletions(-) create mode 100644 skills/rfp-response/evidence/clean-install.json create mode 100644 skills/rfp-response/evidence/clean-install.stderr.txt create mode 100644 skills/rfp-response/evidence/evidence.json create mode 100644 skills/rfp-response/evidence/hosted-dogfood-output.json create mode 100644 skills/rfp-response/evidence/hosted-dogfood-output.stderr.txt create mode 100644 skills/rfp-response/evidence/hosted-dogfood-receipts-linux.tgz create mode 100644 skills/rfp-response/evidence/hosted-harness-receipts-linux.tgz create mode 100644 skills/rfp-response/evidence/hosted-harness-verification.json create mode 100644 skills/rfp-response/evidence/hosted-harness-verification.stderr.txt create mode 100644 skills/rfp-response/evidence/hosted-harness.json create mode 100644 skills/rfp-response/evidence/hosted-harness.stderr.txt create mode 100644 skills/rfp-response/evidence/hosted-verification.json create mode 100644 skills/rfp-response/evidence/hosted-verification.stderr.txt create mode 100644 skills/rfp-response/evidence/registry-read.json create mode 100644 skills/rfp-response/evidence/registry-read.stderr.txt create mode 100644 skills/rfp-response/evidence/report.md diff --git a/skills/rfp-response/evidence/clean-install.json b/skills/rfp-response/evidence/clean-install.json new file mode 100644 index 000000000..b46bbbdb8 --- /dev/null +++ b/skills/rfp-response/evidence/clean-install.json @@ -0,0 +1,43 @@ +{ + "status": "success", + "registry": { + "action": "install", + "source": "remote", + "ref": "lubuseb/rfp-response@sha-68462d4db0fd", + "install": { + "status": "installed", + "destination": "/tmp/runx-rfp-response-clean-install/lubuseb/rfp-response/sha-68462d4db0fd/SKILL.md", + "skill_name": "rfp-response", + "source": "runx-registry", + "source_label": "runx registry", + "skill_id": "lubuseb/rfp-response", + "version": "sha-68462d4db0fd", + "digest": "sha256:53684267a1bca9969949207600ca436940ced49500ff3a6381e7f3a375458f9e", + "profile_digest": "sha256:75bfeb70a9559a6ed9d077c7d4f8d0db786191172fc7fbe5eeadaef67b07543c", + "profile_state_path": "/tmp/runx-rfp-response-clean-install/lubuseb/rfp-response/sha-68462d4db0fd/.runx/profile.json", + "runner_names": [ + "default" + ], + "trust_tier": "community" + }, + "receipt_metadata": { + "destination": "/tmp/runx-rfp-response-clean-install/lubuseb/rfp-response/sha-68462d4db0fd/SKILL.md", + "digest": "sha256:53684267a1bca9969949207600ca436940ced49500ff3a6381e7f3a375458f9e", + "install_count": 1, + "package_digest": "3c983bb8018f48bec461085fccd230d657548ac25b3363529aa4a5af10423be5", + "profile_digest": "sha256:75bfeb70a9559a6ed9d077c7d4f8d0db786191172fc7fbe5eeadaef67b07543c", + "publisher": { + "display_name": "LubuSeb", + "handle": "lubuseb", + "id": "user_53f00ae7ec2363e37ac6ff68", + "kind": "user" + }, + "ref": "lubuseb/rfp-response@sha-68462d4db0fd", + "skill_id": "lubuseb/rfp-response", + "source_label": "runx registry", + "status": "installed", + "trust_tier": "community", + "version": "sha-68462d4db0fd" + } + } +} diff --git a/skills/rfp-response/evidence/clean-install.stderr.txt b/skills/rfp-response/evidence/clean-install.stderr.txt new file mode 100644 index 000000000..e69de29bb diff --git a/skills/rfp-response/evidence/evidence.json b/skills/rfp-response/evidence/evidence.json new file mode 100644 index 000000000..afcd09122 --- /dev/null +++ b/skills/rfp-response/evidence/evidence.json @@ -0,0 +1,132 @@ +{ + "schema": "frantic.delivery.evidence.v1", + "summary": "rfp-response was published as a hosted runx skill, clean-installed from the registry, harnessed from the installed package, dogfooded on a cited questionnaire input, and verified with a sealed production-mode runx receipt.", + "artifact": "rfp-response", + "package": { + "owner": "lubuseb", + "name": "rfp-response", + "version": "sha-68462d4db0fd", + "registry_ref": "lubuseb/rfp-response@sha-68462d4db0fd", + "public_url": "https://runx.ai/x/lubuseb/rfp-response@sha-68462d4db0fd", + "registry_public_url": "https://runx.ai/x/lubuseb/rfp-response", + "digest": "53684267a1bca9969949207600ca436940ced49500ff3a6381e7f3a375458f9e", + "profile_digest": "75bfeb70a9559a6ed9d077c7d4f8d0db786191172fc7fbe5eeadaef67b07543c" + }, + "source": { + "pr_url": "https://github.com/runxhq/runx/pull/125", + "source_url": "https://github.com/LubuSeb/runx/tree/rfp-response-54/skills/rfp-response", + "x_yaml": "https://raw.githubusercontent.com/LubuSeb/runx/rfp-response-54/skills/rfp-response/X.yaml", + "skill_md": "https://raw.githubusercontent.com/LubuSeb/runx/rfp-response-54/skills/rfp-response/SKILL.md" + }, + "runtime": { + "runx_version": "runx-cli 0.6.13", + "receipt_ref": "runx:receipt:sha256:3a5fe208e9bc5f06920a60b1abee55d874d2e7b72b6e99ac9f3e35f17cc9a3fc", + "receipt_id": "sha256:3a5fe208e9bc5f06920a60b1abee55d874d2e7b72b6e99ac9f3e35f17cc9a3fc", + "verify_verdict": "valid", + "signature_mode": "production" + }, + "dogfood": { + "command": "runx skill lubuseb/rfp-response@sha-68462d4db0fd --registry https://api.runx.ai --input-json questionnaire= --input-json knowledge_pack= --json", + "package": "lubuseb/rfp-response@sha-68462d4db0fd", + "input": "fixtures/supported-questionnaire.json", + "receipt_ref": "runx:receipt:sha256:3a5fe208e9bc5f06920a60b1abee55d874d2e7b72b6e99ac9f3e35f17cc9a3fc", + "verification_json": "hosted-verification.json", + "verify_verdict": "valid", + "harness_cases": [ + { + "name": "cited-security-questionnaire-answers", + "status": "sealed" + }, + { + "name": "unsupported-certification-is-gap", + "status": "refused" + }, + { + "name": "missing-knowledge-pack-fails-closed", + "status": "failure" + } + ], + "answered_count": 2, + "gap_count": 0, + "sample_citations": [ + { + "claim_id": "enc-1", + "source_id": "security-overview", + "title": "Acme Security Overview 2026", + "url": "https://example.com/acme/security-overview" + } + ] + }, + "observations": [ + { + "name": "runx_version", + "status": "passed", + "detail": "npx --yes @runxhq/cli@latest --version returned: runx-cli 0.6.13", + "evidence_ref": "runx-version.txt" + }, + { + "name": "published_registry_package", + "status": "passed", + "detail": "runx registry publish completed successfully for lubuseb/rfp-response@sha-68462d4db0fd on https://api.runx.ai.", + "evidence_ref": "registry-publish.json" + }, + { + "name": "public_url_binding", + "status": "passed", + "detail": "Submitted public_url is the version-pinned registry page https://runx.ai/x/lubuseb/rfp-response@sha-68462d4db0fd; registry-publish.json also reports the unversioned landing page https://runx.ai/x/lubuseb/rfp-response.", + "evidence_ref": "registry-publish.json" + }, + { + "name": "clean_install", + "status": "passed", + "detail": "runx add installed lubuseb/rfp-response@sha-68462d4db0fd into a clean directory.", + "evidence_ref": "clean-install.json" + }, + { + "name": "hosted_harness", + "status": "passed", + "detail": "The installed registry package passed cited-answer, unsupported-gap, and fail-closed harness cases: cited-security-questionnaire-answers=sealed, unsupported-certification-is-gap=refused, missing-knowledge-pack-fails-closed=failure.", + "evidence_ref": "hosted-harness.json" + }, + { + "name": "answered_and_gap_counts", + "status": "passed", + "detail": "Dogfood produced 2 grounded answer(s) and 0 gap(s).", + "evidence_ref": "hosted-dogfood-output.json" + }, + { + "name": "sample_citations", + "status": "passed", + "detail": "[{\"claim_id\":\"enc-1\",\"source_id\":\"security-overview\",\"title\":\"Acme Security Overview 2026\",\"url\":\"https://example.com/acme/security-overview\"}]", + "evidence_ref": "hosted-dogfood-output.json" + }, + { + "name": "dogfood_receipt_verified", + "status": "passed", + "detail": "runx verify accepted receipt sha256:3a5fe208e9bc5f06920a60b1abee55d874d2e7b72b6e99ac9f3e35f17cc9a3fc with no findings.", + "evidence_ref": "hosted-verification.json" + }, + { + "name": "receipt_id", + "status": "passed", + "detail": "Post-publish dogfood receipt id: sha256:3a5fe208e9bc5f06920a60b1abee55d874d2e7b72b6e99ac9f3e35f17cc9a3fc.", + "evidence_ref": "hosted-verification.json" + }, + { + "name": "read_only_behavior", + "status": "passed", + "detail": "The runner reads JSON inputs, computes deterministically in memory, performs no provider calls, emits no effect, and emits structured stdout only.", + "evidence_ref": "run.mjs" + } + ], + "commands": [ + "npx --yes @runxhq/cli@latest --version", + "npx --yes @runxhq/cli@latest harness /mnt/f/BountyBar/repos/runx/skills/rfp-response --json", + "npx --yes @runxhq/cli@latest registry publish /mnt/f/BountyBar/repos/runx/skills/rfp-response/SKILL.md --registry https://api.runx.ai --json", + "npx --yes @runxhq/cli@latest registry read lubuseb/rfp-response@sha-68462d4db0fd --registry https://api.runx.ai --json", + "npx --yes @runxhq/cli@latest add lubuseb/rfp-response@sha-68462d4db0fd --registry https://api.runx.ai --to /tmp/runx-rfp-response-clean-install --json", + "npx --yes @runxhq/cli@latest harness /tmp/runx-rfp-response-clean-install/lubuseb/rfp-response/ --json", + "npx --yes @runxhq/cli@latest skill lubuseb/rfp-response@sha-68462d4db0fd --registry https://api.runx.ai --input-json questionnaire= --input-json knowledge_pack= --json", + "npx --yes @runxhq/cli@latest verify --receipt-dir /tmp/runx-rfp-response-hosted-dogfood-receipts --json" + ] +} diff --git a/skills/rfp-response/evidence/hosted-dogfood-output.json b/skills/rfp-response/evidence/hosted-dogfood-output.json new file mode 100644 index 000000000..24f8a0c5b --- /dev/null +++ b/skills/rfp-response/evidence/hosted-dogfood-output.json @@ -0,0 +1,359 @@ +{ + "closure": { + "closed_at": "2026-06-23T05:13:25.514Z", + "disposition": "closed", + "reason_code": "process_closed", + "summary": "cli-tool default completed" + }, + "execution": { + "exit_code": 0, + "skill_claim": { + "answers": [ + { + "answer": "Customer data is encrypted at rest with AES-256 and in transit with TLS 1.2 or newer.", + "citations": [ + { + "claim_id": "enc-1", + "source_id": "security-overview", + "title": "Acme Security Overview 2026", + "url": "https://example.com/acme/security-overview" + } + ], + "confidence": "high", + "q": "q1", + "question": "Do you encrypt customer data at rest and in transit?", + "section": "encryption" + }, + { + "answer": "Production access is limited to approved on-call engineers, requires MFA, and is reviewed quarterly.", + "citations": [ + { + "claim_id": "access-1", + "source_id": "security-overview", + "title": "Acme Security Overview 2026", + "url": "https://example.com/acme/security-overview" + } + ], + "confidence": "medium", + "q": "q2", + "question": "How do you restrict production access?", + "section": "access" + } + ], + "evidence_json": { + "artifact": "rfp-response", + "knowledge_digest": "sha256:acbefb0d1a1a85c3b58fe86d7137f7de79a8eb5f0453116f32dcf6c43b0fc460", + "objective": "Draft grounded security questionnaire answers for a vendor review.", + "observations": { + "answered_count": 2, + "effect_emitted": false, + "gap_count": 0, + "network_used": false, + "read_only": true, + "refused_questions": [], + "sample_citations": [ + { + "claim_id": "enc-1", + "source_id": "security-overview", + "title": "Acme Security Overview 2026", + "url": "https://example.com/acme/security-overview" + }, + { + "claim_id": "access-1", + "source_id": "security-overview", + "title": "Acme Security Overview 2026", + "url": "https://example.com/acme/security-overview" + } + ] + }, + "questionnaire_digest": "sha256:f2428f3d99f2d48e9c64b554dd734057a7a9f591682f1cd77a5a11487eac82b7", + "schema": "frantic.delivery.evidence.v1" + }, + "gaps": [], + "report": "# rfp-response report\n\nAnswered questions: 2\nGaps: 0\nKnowledge sources: 1\n\n## Answers\n- q1: Customer data is encrypted at rest with AES-256 and in transit with TLS 1.2 or newer. Citations: security-overview/enc-1\n- q2: Production access is limited to approved on-call engineers, requires MFA, and is reviewed quarterly. Citations: security-overview/access-1\n\n## Gaps\n- none\n\nThe draft is read-only and requires human approval before external use." + }, + "stderr": "", + "stdout": "{\n \"answers\": [\n {\n \"q\": \"q1\",\n \"question\": \"Do you encrypt customer data at rest and in transit?\",\n \"section\": \"encryption\",\n \"answer\": \"Customer data is encrypted at rest with AES-256 and in transit with TLS 1.2 or newer.\",\n \"citations\": [\n {\n \"source_id\": \"security-overview\",\n \"claim_id\": \"enc-1\",\n \"title\": \"Acme Security Overview 2026\",\n \"url\": \"https://example.com/acme/security-overview\"\n }\n ],\n \"confidence\": \"high\"\n },\n {\n \"q\": \"q2\",\n \"question\": \"How do you restrict production access?\",\n \"section\": \"access\",\n \"answer\": \"Production access is limited to approved on-call engineers, requires MFA, and is reviewed quarterly.\",\n \"citations\": [\n {\n \"source_id\": \"security-overview\",\n \"claim_id\": \"access-1\",\n \"title\": \"Acme Security Overview 2026\",\n \"url\": \"https://example.com/acme/security-overview\"\n }\n ],\n \"confidence\": \"medium\"\n }\n ],\n \"gaps\": [],\n \"evidence_json\": {\n \"schema\": \"frantic.delivery.evidence.v1\",\n \"artifact\": \"rfp-response\",\n \"objective\": \"Draft grounded security questionnaire answers for a vendor review.\",\n \"knowledge_digest\": \"sha256:acbefb0d1a1a85c3b58fe86d7137f7de79a8eb5f0453116f32dcf6c43b0fc460\",\n \"questionnaire_digest\": \"sha256:f2428f3d99f2d48e9c64b554dd734057a7a9f591682f1cd77a5a11487eac82b7\",\n \"observations\": {\n \"answered_count\": 2,\n \"gap_count\": 0,\n \"sample_citations\": [\n {\n \"source_id\": \"security-overview\",\n \"claim_id\": \"enc-1\",\n \"title\": \"Acme Security Overview 2026\",\n \"url\": \"https://example.com/acme/security-overview\"\n },\n {\n \"source_id\": \"security-overview\",\n \"claim_id\": \"access-1\",\n \"title\": \"Acme Security Overview 2026\",\n \"url\": \"https://example.com/acme/security-overview\"\n }\n ],\n \"refused_questions\": [],\n \"read_only\": true,\n \"network_used\": false,\n \"effect_emitted\": false\n }\n },\n \"report\": \"# rfp-response report\\n\\nAnswered questions: 2\\nGaps: 0\\nKnowledge sources: 1\\n\\n## Answers\\n- q1: Customer data is encrypted at rest with AES-256 and in transit with TLS 1.2 or newer. Citations: security-overview/enc-1\\n- q2: Production access is limited to approved on-call engineers, requires MFA, and is reviewed quarterly. Citations: security-overview/access-1\\n\\n## Gaps\\n- none\\n\\nThe draft is read-only and requires human approval before external use.\"\n}\n", + "structured_output": { + "answers": [ + { + "answer": "Customer data is encrypted at rest with AES-256 and in transit with TLS 1.2 or newer.", + "citations": [ + { + "claim_id": "enc-1", + "source_id": "security-overview", + "title": "Acme Security Overview 2026", + "url": "https://example.com/acme/security-overview" + } + ], + "confidence": "high", + "q": "q1", + "question": "Do you encrypt customer data at rest and in transit?", + "section": "encryption" + }, + { + "answer": "Production access is limited to approved on-call engineers, requires MFA, and is reviewed quarterly.", + "citations": [ + { + "claim_id": "access-1", + "source_id": "security-overview", + "title": "Acme Security Overview 2026", + "url": "https://example.com/acme/security-overview" + } + ], + "confidence": "medium", + "q": "q2", + "question": "How do you restrict production access?", + "section": "access" + } + ], + "evidence_json": { + "artifact": "rfp-response", + "knowledge_digest": "sha256:acbefb0d1a1a85c3b58fe86d7137f7de79a8eb5f0453116f32dcf6c43b0fc460", + "objective": "Draft grounded security questionnaire answers for a vendor review.", + "observations": { + "answered_count": 2, + "effect_emitted": false, + "gap_count": 0, + "network_used": false, + "read_only": true, + "refused_questions": [], + "sample_citations": [ + { + "claim_id": "enc-1", + "source_id": "security-overview", + "title": "Acme Security Overview 2026", + "url": "https://example.com/acme/security-overview" + }, + { + "claim_id": "access-1", + "source_id": "security-overview", + "title": "Acme Security Overview 2026", + "url": "https://example.com/acme/security-overview" + } + ] + }, + "questionnaire_digest": "sha256:f2428f3d99f2d48e9c64b554dd734057a7a9f591682f1cd77a5a11487eac82b7", + "schema": "frantic.delivery.evidence.v1" + }, + "gaps": [], + "report": "# rfp-response report\n\nAnswered questions: 2\nGaps: 0\nKnowledge sources: 1\n\n## Answers\n- q1: Customer data is encrypted at rest with AES-256 and in transit with TLS 1.2 or newer. Citations: security-overview/enc-1\n- q2: Production access is limited to approved on-call engineers, requires MFA, and is reviewed quarterly. Citations: security-overview/access-1\n\n## Gaps\n- none\n\nThe draft is read-only and requires human approval before external use." + } + }, + "payload": { + "answers": [ + { + "answer": "Customer data is encrypted at rest with AES-256 and in transit with TLS 1.2 or newer.", + "citations": [ + { + "claim_id": "enc-1", + "source_id": "security-overview", + "title": "Acme Security Overview 2026", + "url": "https://example.com/acme/security-overview" + } + ], + "confidence": "high", + "q": "q1", + "question": "Do you encrypt customer data at rest and in transit?", + "section": "encryption" + }, + { + "answer": "Production access is limited to approved on-call engineers, requires MFA, and is reviewed quarterly.", + "citations": [ + { + "claim_id": "access-1", + "source_id": "security-overview", + "title": "Acme Security Overview 2026", + "url": "https://example.com/acme/security-overview" + } + ], + "confidence": "medium", + "q": "q2", + "question": "How do you restrict production access?", + "section": "access" + } + ], + "evidence_json": { + "artifact": "rfp-response", + "knowledge_digest": "sha256:acbefb0d1a1a85c3b58fe86d7137f7de79a8eb5f0453116f32dcf6c43b0fc460", + "objective": "Draft grounded security questionnaire answers for a vendor review.", + "observations": { + "answered_count": 2, + "effect_emitted": false, + "gap_count": 0, + "network_used": false, + "read_only": true, + "refused_questions": [], + "sample_citations": [ + { + "claim_id": "enc-1", + "source_id": "security-overview", + "title": "Acme Security Overview 2026", + "url": "https://example.com/acme/security-overview" + }, + { + "claim_id": "access-1", + "source_id": "security-overview", + "title": "Acme Security Overview 2026", + "url": "https://example.com/acme/security-overview" + } + ] + }, + "questionnaire_digest": "sha256:f2428f3d99f2d48e9c64b554dd734057a7a9f591682f1cd77a5a11487eac82b7", + "schema": "frantic.delivery.evidence.v1" + }, + "gaps": [], + "report": "# rfp-response report\n\nAnswered questions: 2\nGaps: 0\nKnowledge sources: 1\n\n## Answers\n- q1: Customer data is encrypted at rest with AES-256 and in transit with TLS 1.2 or newer. Citations: security-overview/enc-1\n- q2: Production access is limited to approved on-call engineers, requires MFA, and is reviewed quarterly. Citations: security-overview/access-1\n\n## Gaps\n- none\n\nThe draft is read-only and requires human approval before external use." + }, + "receipt": { + "acts": [ + { + "artifact_refs": [], + "closure": { + "closed_at": "2026-06-23T05:13:25.514Z", + "disposition": "closed", + "reason_code": "process_exit", + "summary": "cli-tool exited successfully" + }, + "criterion_bindings": [ + { + "criterion_id": "process_exit", + "evidence_refs": [], + "status": "verified", + "summary": "cli-tool exited successfully", + "verification_refs": [] + } + ], + "form": "observation", + "id": "act_default", + "intent": { + "constraints": [], + "derived_from": [], + "legitimacy": "Runtime graph execution was admitted by the local harness", + "purpose": "Run graph step default", + "success_criteria": [ + { + "criterion_id": "process_exit", + "required": true, + "statement": "cli-tool exits successfully" + } + ] + }, + "source_refs": [], + "summary": "Executed graph step default", + "target_refs": [] + } + ], + "authority": { + "actor_ref": { + "type": "principal", + "uri": "runx:principal:local_runtime" + }, + "attenuation": { + "parent_authority_ref": null, + "subset_proof": null + }, + "authority_proof_refs": [], + "enforcement": { + "profile_hash": "sha256:runtime-skeleton-enforcement", + "redaction_refs": [], + "setup_refs": [], + "teardown_refs": [] + }, + "grant_refs": [], + "scope_refs": [], + "terms": [] + }, + "canonicalization": "runx.receipt.c14n.v1", + "created_at": "2026-06-23T05:13:25.514Z", + "decisions": [ + { + "artifact_refs": [], + "choice": "open", + "closure": null, + "decision_id": "dec_default", + "inputs": { + "opportunity_refs": [], + "selection_ref": null, + "signal_refs": [], + "target_ref": null + }, + "justification": { + "evidence_refs": [], + "summary": "runtime graph planner selected this node" + }, + "proposed_intent": { + "constraints": [], + "derived_from": [], + "legitimacy": "Local graph execution requested this node", + "purpose": "Open runtime node default", + "success_criteria": [] + }, + "selected_act_id": "act_default", + "selected_harness_ref": null + } + ], + "digest": "sha256:594fbed42684466e0944f2a71fde288632cfd03b6c46f851976735712f7911ab", + "id": "sha256:3a5fe208e9bc5f06920a60b1abee55d874d2e7b72b6e99ac9f3e35f17cc9a3fc", + "idempotency": { + "content_hash": "sha256:run_default_ce6bab504068-default-content", + "intent_key": "sha256:run_default_ce6bab504068-default-intent", + "trigger_fingerprint": "sha256:run_default_ce6bab504068-default-trigger" + }, + "issuer": { + "kid": "local:bountybar-frantic-runx-22-20260618192655", + "public_key_sha256": "sha256:afae74faf1b1b104b27d788bee2dd0982052af89a1ae30b3282f1a14b0707871", + "type": "hosted" + }, + "lineage": { + "children": [], + "sync": [] + }, + "schema": "runx.receipt.v1", + "seal": { + "closed_at": "2026-06-23T05:13:25.514Z", + "criteria": [ + { + "criterion_id": "process_exit", + "evidence_refs": [], + "status": "verified", + "summary": "cli-tool exited successfully", + "verification_refs": [] + } + ], + "disposition": "closed", + "last_observed_at": "2026-06-23T05:13:25.514Z", + "reason_code": "process_closed", + "summary": "cli-tool default completed" + }, + "signals": [], + "signature": { + "alg": "Ed25519", + "value": "base64:16ywgu9r91duHEhHrHllzb9MMIBZplokG6Q36fbplGVtvDucjP0V09Hd3D0cY5dusVKq_nXzFrHLtxHy0lshDg" + }, + "subject": { + "commitments": [], + "kind": "skill", + "ref": { + "type": "harness", + "uri": "hrn_run_default_ce6bab504068_default" + } + } + }, + "receipt_id": "sha256:3a5fe208e9bc5f06920a60b1abee55d874d2e7b72b6e99ac9f3e35f17cc9a3fc", + "registry_provenance": { + "digest": "sha256:53684267a1bca9969949207600ca436940ced49500ff3a6381e7f3a375458f9e", + "profile_digest": "sha256:75bfeb70a9559a6ed9d077c7d4f8d0db786191172fc7fbe5eeadaef67b07543c", + "registry_key_id": "runx-registry-ed25519-v1", + "registry_source": "remote https://api.runx.ai", + "registry_source_fingerprint": "ba1ac16b631195fd", + "skill_id": "lubuseb/rfp-response", + "trust_state": "trusted", + "trust_tier": "community", + "version": "sha-68462d4db0fd" + }, + "run_id": "run_default_ce6bab504068", + "schema": "runx.skill_run.v1", + "skill_name": "rfp-response", + "status": "sealed" +} diff --git a/skills/rfp-response/evidence/hosted-dogfood-output.stderr.txt b/skills/rfp-response/evidence/hosted-dogfood-output.stderr.txt new file mode 100644 index 000000000..e69de29bb diff --git a/skills/rfp-response/evidence/hosted-dogfood-receipts-linux.tgz b/skills/rfp-response/evidence/hosted-dogfood-receipts-linux.tgz new file mode 100644 index 0000000000000000000000000000000000000000..7a078c4382d545aa6df1f6e706b7de46cf21b814 GIT binary patch literal 1504 zcmV<61t0n!iwFP!000001MOGaZrnBy^`{7W_By2Q+NYvO8W(lZHYkENMIlhsXqT~; zR7lG4#_+#)C~0qr9j}925LB}dT9MSunVB;~Qg`xtrt5a5!L&*mm@SpDP|Yf}sFkX4 zoP%hsd2;f}LQv8;c2AndWPH+oe3TO!2Q-OjkS4f}reR13xv{yq$l3R7s7KOoBV5~?8nwU zH2_d7$wt0L{`>kT3T)4M>p8NHPn;KS?~N;XH`XVj8`2>zGthaMp-- z%nBvn$Hr+SM}Wq3p#AxcZ`Up0x`DhnbJ=5W6l$55s*`qIGCiv`lUDFq&-x&kIS?eF z8O?(vj`6d$D;vR!OIR0!-@5>?nn4=XtfnRYNK^)Cm1Y^bA5;~|vw*|_tFxR@1|ccK zAPZ{BXjGDvq*+S++f(0&g=DtV;2^VRf!d!{K^)T@ZC|mbb3T;JKoZSqvVObha-Gwv zJAbx3*XK?1uFQY^_2(a7wT-%bp8OFeb=fx0U)rmu9e@2hc}eo~Dtt=#-*MHMm%qFz zhcG&$q+#p7YMS6)SK?7LN2zOK$_6;;Mzc_pQmI#Y0ZLKVvZv-B^P+e#^8A=WczE zOmC*@9k;szBCCb8xQqs`qDsitj+qa_c7x=bK4`yen1a~pVcu7Zc*>)~bH>1LR zvrI3*?gvD*ty48y5^+4j@!2y2TFeyQM z8)XOB;R?Hr zMvQ5DUn*W4c(Y5!TV^~~VaYq6$~C$LUSF@?u7li>nj3$7+3*wz)31SR(Z}54zB-f^ zMncT2QjO>4j5lhlF)Zu8gx+)l>&Ty5-NEg#Ip3z~S?>yhzcU6qlqGgc?B3=`@EtDn zuW(H*`rZ436rYZ>19kQbY76baaYT6Fx%1ShP9Lb;744?qy-%AxVqvQgctSQ}JdwDG z9xEPd@J3T`N6rtOI}YCIsP2KI(QWSrVDEn{obB`-fX4iJxEZzBcKc;V!9mh9V~e3^ zjycyoj?rI%6v*vHNMMUT!F(y23b(jX$y)MZ1Nqix^e-vL-~X_p;rf$q?+@JnNQ8I3 z!}}i%gLJz8eGR$i{#O`0c|tMdyuWHK05{~_^^K-kKy#XqI1WORC3)(uFt`P20Ylf{ zX!^{T$o|+U*$O_N)}GWy-%qh?eCwo5GRY*9OftzNlT0$nB$G@s$t06JLjD7k7%x5m GC;$Me&H63? literal 0 HcmV?d00001 diff --git a/skills/rfp-response/evidence/hosted-harness-receipts-linux.tgz b/skills/rfp-response/evidence/hosted-harness-receipts-linux.tgz new file mode 100644 index 0000000000000000000000000000000000000000..9f1f1d740c8ea6c6514f512cda7e1ff1f66c55c4 GIT binary patch literal 2436 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