diff --git a/.agents/skills/validate-sas-release/SKILL.md b/.agents/skills/validate-sas-release/SKILL.md index 59a4119c..a40724d7 100644 --- a/.agents/skills/validate-sas-release/SKILL.md +++ b/.agents/skills/validate-sas-release/SKILL.md @@ -84,3 +84,7 @@ For Brazil source-state candidates, reuse the existing compiled-playbook batch, After a complete four-playbook cohort passes primary review and strict reconstruction, reuse `sync:content --new-version` to prepare exact draft archives, compare all four archive digests to the frozen plan, and dry-run the atomic import with rollback before applying it. Retain a fresh native `registry.json` snapshot with immutable package/version IDs, source/archive SHA256, draft ownership and zero price. Run `node --experimental-strip-types scripts/prepare-solution-registry.mjs EVIDENCE_DIR NEW_SQL`: it independently reruns the strict report, rejects stale/incomplete/source/model bindings and prepares only qualifying model-scoped adversarial/compatibility records. It never changes publication/review flags. Validate SQL in rollback, then use the authenticated admin review UI and verify actual persisted/public versions afterward. Synthetic binding tests cover partial/duplicate/stale/public/broad-model/failed-primary reports; they are not live qualification. After authenticated four-playbook publication, run `node --experimental-strip-types scripts/check-solution-publication.mjs EVIDENCE_DIR HTTPS_ORIGIN NEW_REPORT`. It rejects empty/stale targets, checks all public versions/source hashes and exclusive recorded runtimes, downloads each public ZIP and verifies every frozen file hash plus the complete artifact digest. It also verifies any configured detached ZIP signature; absence of signing configuration is recorded rather than represented as a verified signature. No model calls, writes or automatic retries. Re-run the existing21skill publication verifier and `check:security` after a public metadata change. The public package endpoint must select the registry's exact latest_version, and newly exposed recorded compatibility must match current source/archive, actual reviewed outcomes, severity counts/scores, protocol and version; never broaden a claim from a table row alone. + +For model-scoped marketplace presentation, reuse the private `loadPublicEvaluationCompatibility` loader for both API metadata and detail pages; independent renderers must not substitute an empty declared array or a different version. Packaged execution guides require a supported runtime and distinguish source-state preparation from the separate local-model runner. Keep the complete evaluated ZIP, signature links, exact environment and source-upload consent visible; bare prompts, generic MCP installation and historical versions inherit no qualification. Run the real SSR regressions in `tests/packaged-execution-ui.test.ts` through the normal batch, then inspect the actual public page/compatibility counts. A missing runtime must block installation cleanly rather than dereferencing an empty array. Candidate UI validation passed333tests and12checks, including unchanged RLS/anonymous-access gates; no model/package contents changed. + +Reuse `node scripts/check-public-version.mjs EXPECTED_VERSION CANONICAL_HTTPS_ORIGIN ALIAS_HTTPS_ORIGIN NEW_REPORT` after deployment. It makes exactly two anonymous reads without retries, requires the exact canonical version, and accepts an alias redirect only to that explicit canonical version endpoint. Foreign origins, added query parameters, stale versions and unknown observations fail. This exception is specific to the owned publication alias; model/source-upload transports retain their no-redirect policy. Actual0.7.0 verification passed2/2: the platform alias returned302to the canonical version endpoint, which returned200/version0.7.0. Earlier strict no-redirect probes remain preserved. diff --git a/docs/ADVERSARIAL-BUSINESS-EVALUATION.md b/docs/ADVERSARIAL-BUSINESS-EVALUATION.md index 4eb29662..eb3e2dc1 100644 --- a/docs/ADVERSARIAL-BUSINESS-EVALUATION.md +++ b/docs/ADVERSARIAL-BUSINESS-EVALUATION.md @@ -405,3 +405,9 @@ All four0.1.31 versions were approved through the existing authenticated Chrome Public verification then caught a metadata gap: the portable archives were current, but `/api/public/packages/:slug` returned the version's empty declared compatibility instead of the recorded qualification. `check-solution-publication.mjs` reproduced0/4 before the fix. The API now pins its source query to `packages.latest_version` and adds recorded compatibility only after checking actual current-version run/outcomes, primary decisions, zero high/critical failures, exact weighted/count calculations and source/archive/protocol bindings. It exposes only that evaluated runtime when adding evidence; existing declarations without a usable recorded run remain declarations rather than new qualification. No immutable package/source/archive was rewritten. The API helper passed2tests with13negative mutations; real current database fields mapped4/4to the expected exact-runtime claims in an offline helper probe (not a deployed HTTP proof). The complete batch passed331tests and all12checks including RLS/anonymous-access coverage, with unchanged allowlists (`artifacts/solution-public-api-project-security.json`). Deploy this metadata fix, then require the four-package public verifier to pass against real HTTP and exact ZIP files; retain the pre-fix failure and all original model histories. + +Platform0.7.0 (PR75, commit034beaa7) was validated after the version bot (331tests/12checks), matched the native Lovable source and deployed directly without any builder message or inference. Production anonymous checks passed4/4source-state packages and21/21individual skills. All136frozen archive files and all4configured Ed25519 ZIP signatures verified; post-deployment RLS/anonymous-access checks passed across92tables without allowlist changes. Actual deployment/version/public/security receipts are retained in `artifacts/release-source-state-solutions`. + +Visual verification then caught that marketplace pages still used declared compatibility only, displayed0runtimes and offered generic prompt/MCP instructions for packaged execution. The UI correction shares the same private source-bound compatibility loader with the API, selects the exact current version, recommends the complete evaluated ZIP/profile and explicit source-upload consent, and does not imply that prompt copying, arbitrary clients or historical versions are covered by the current evaluation. It also handles missing-runtime install preflight without a crash. Actual React SSR tests verify bundle/consent/preview output and reject partial/unsupported runtime declarations; all333tests and12project/security checks passed. These presentation changes do not modify immutable0.1.31archives or their original72case qualification. Deployment and visual/public verification of this follow-up remain pending. + +The platform alias now redirects302to the canonical public version endpoint. Earlier probes used `redirect:error` and correctly recorded that redirect as a nonpassing direct response; no deployment was restarted. The small reusable `check-public-version.mjs` verifies the exact canonical version and permits only the explicit owned alias destination, never foreign origins or query-bearing redirects. Its2regressions passed and the real0.7.0batch passed2/2. Model/source transport rules and the original qualification criteria remain unchanged. diff --git a/docs/PLAYBOOK-RUNTIME-QUALIFICATION.md b/docs/PLAYBOOK-RUNTIME-QUALIFICATION.md index c0ecc4bd..ff55ed96 100644 --- a/docs/PLAYBOOK-RUNTIME-QUALIFICATION.md +++ b/docs/PLAYBOOK-RUNTIME-QUALIFICATION.md @@ -1,8 +1,17 @@ # Solution playbook runtime qualification -The four standalone `solution-*` playbooks remain unqualified. Their solution -pages and the approval of 21 individual skills do not approve execution of these -compiled workflows. No production publication is authorized by this document. +The four standalone `solution-*` playbooks qualified as immutable version0.1.31 +under their exact source-state model/runtime profiles and were published through +authenticated administrator review. All72original cases passed primary source +review and strict parser/provider/stage reconstruction, with zero high/critical +failures. Publication does not transfer qualification to bare prompts, other +models, MCP transport alone or external financial/sending/security actions. + +Current scope is Jev1.14.0 and each packaged Node24.22.0/arm64 protocol; Brazil also +pins Python3.12.15/Expat2.7.4. The21individual skills retain their separate packaged +local-model qualification. See `ADVERSARIAL-BUSINESS-EVALUATION.md` for current +proofs. The investigations below preserve historical candidate/failed protocols +and never supersede the original approval criteria. The gateway CLI previously dropped `RunContext.inputs` and `RunContext.steps`. The real CLI regression reproduced that omission and acceptance of both empty and diff --git a/docs/adr/20261025-finance-source-state.md b/docs/adr/20261025-finance-source-state.md index 27ffb44d..f10e4f5d 100644 --- a/docs/adr/20261025-finance-source-state.md +++ b/docs/adr/20261025-finance-source-state.md @@ -1,6 +1,7 @@ # Finance preparation uses typed state and source interpretation -Status: implemented candidate; qualification and publication pending. +Status: implemented; exact source-state profiles qualified and published at0.1.31. +The initial decision below is historical; see the final-scope note at the end. Repeated real compiled-graph pilots preserved correct arithmetic but confused budget approval, unmatched-entry ownership and authority to post/pay/sign off. @@ -20,7 +21,8 @@ No generative model drafts the four finance stage outputs. This is an actual execution-protocol change, not output repair, a replay or a mock substitute for a model benchmark. Finance qualification is scoped to `jev-1.14.0`, the pinned Node host and packaged finance-source-state protocol. It makes no Gemma quality claim. -The other three playbooks continue using the pinned local generator. Agent Match's +At the initial decision, the other three playbooks continued using the pinned +local generator; their later source-state migrations supersede that arrangement. Agent Match's same-generator comparison and financial cap are unaffected. The frozen four-subject/72-case contract, original severities, expectations, @@ -28,7 +30,9 @@ thresholds, primary trace reviews and zero high/critical bar remain unchanged. Finance evidence must contain a real source-interpretation response with model and usage plus four actual accounting-tool receipts. The strict reporter rejects any unexpected finance generation and recomputes each stage from the validated source -evidence. Other playbooks still require complete raw generation transports. No +evidence. At that initial stage, other playbooks still required complete raw generation +transports. Their final source-state protocols instead require actual interpreter +receipts and independently reconstructed tool outputs. No prior qualification transfers to this protocol; all 72 cases remain required. Authenticated external controller approval is a separate future integration. Until @@ -40,3 +44,17 @@ human gate. It cannot claim that the business month is signed off. The complete-output v12 run retained 19 real cases before an operator boundary stop. Accounting values and pending approval were correct in all 18 finance cases, but seven original baseline response requirements failed, including critical explicit-refusal omissions. Supplier generation also miscomputed landed cost. These failures remain preserved and block publication. Finance v2 adds one bounded TypeSafe classification of locally sanitized attachment context, explicitly separate from original accounting sources. The selected safety response cannot authorize actions or change arithmetic. The raw model distribution remains in the provider evidence and all four actual preparation outputs retain the response. Sensitive attachment values and destinations are omitted before remote interpretation; unresolved detected leaks reject upload. This is a response-boundary correction, not a qualification claim. It requires a new package version, fresh source-bound run and unchanged case/scorer gates. + +## Final qualified scope and presentation + +All four0.1.31 graphs now use source-state preparation: finance-v3, supplier-v1, +security-v1 and Brazil-v1, pinned to Jev1.14.0/Node24.22.0/arm64. Brazil additionally +pins Python3.12.15/Expat2.7.4. The complete72case cohort used108actual TypeSafe +requests and zero generative requests; the MLX server was harness-only. No +generative-model or live-action qualification is inherited. All original cases, +thresholds, primary decisions and immutable archive/source bindings remain. + +The marketplace must present the complete bundle and recorded runtime, rather +than treating a copied prompt, arbitrary MCP client or historical version as +that evaluated execution. API and page compatibility use the same bound evidence +loader. External authority remains pending independently of package approval. diff --git a/scripts/check-public-version.mjs b/scripts/check-public-version.mjs new file mode 100644 index 00000000..2a6b94ea --- /dev/null +++ b/scripts/check-public-version.mjs @@ -0,0 +1,77 @@ +/** Two anonymous version reads, allowing only the explicit owned canonical redirect. */ +import { existsSync, writeFileSync } from "node:fs"; +import { resolve } from "node:path"; +import { pathToFileURL } from "node:url"; +export function versionResults(expected, canonical, alias, observations) { + const primary = observations[0], + secondary = observations[1]; + const primaryPassed = primary?.status === 200 && primary.data?.version === expected; + const direct = secondary?.status === 200 && secondary.data?.version === expected; + let canonicalRedirect = false; + try { + canonicalRedirect = + [301, 302, 303, 307, 308].includes(secondary?.status) && + new URL(secondary.location, alias).href === `${canonical}/api/public/version`; + } catch {} + return [ + { origin: canonical, ...primary, passed: primaryPassed }, + { + origin: alias, + status: secondary?.status ?? null, + version: secondary?.data?.version ?? null, + error: secondary?.error ?? null, + canonical_redirect: canonicalRedirect, + passed: primaryPassed && (direct || canonicalRedirect), + }, + ]; +} +async function main() { + const [expected, canonical, alias, output] = process.argv.slice(2); + if ( + process.argv.length !== 6 || + !/^\d+\.\d+\.\d+$/.test(expected ?? "") || + !output || + existsSync(output) || + canonical === alias + ) + throw new Error("Supply EXPECTED_VERSION CANONICAL_HTTPS_ORIGIN ALIAS_HTTPS_ORIGIN NEW_REPORT"); + for (const value of [canonical, alias]) { + const u = new URL(value); + if (u.protocol !== "https:" || u.origin !== value || u.username || u.password) + throw new Error("Explicit credential-free HTTPS origins required"); + } + const observations = await Promise.all( + [canonical, alias].map(async (origin) => { + try { + const r = await fetch(origin + "/api/public/version", { + redirect: "manual", + signal: AbortSignal.timeout(15000), + }); + return { + status: r.status, + ...(r.status === 200 + ? { data: await r.json() } + : { location: r.headers.get("location") }), + }; + } catch (error) { + return { status: null, error: String(error) }; + } + }), + ); + const results = versionResults(expected, canonical, alias, observations); + const report = { + checked_at: new Date().toISOString(), + expected_version: expected, + total: 2, + passed: results.filter((r) => r.passed).length, + model_calls: 0, + production_writes: 0, + automatic_retries: 0, + results, + }; + writeFileSync(output, JSON.stringify(report, null, 2) + "\n", { flag: "wx", mode: 0o600 }); + console.log(JSON.stringify({ total: 2, passed: report.passed, report: output })); + process.exitCode = report.passed === 2 ? 0 : 1; +} +if (process.argv[1] && import.meta.url === pathToFileURL(resolve(process.argv[1])).href) + await main(); diff --git a/src/components/marketplace/PackageGallery.tsx b/src/components/marketplace/PackageGallery.tsx index f2eabacd..4befb168 100644 --- a/src/components/marketplace/PackageGallery.tsx +++ b/src/components/marketplace/PackageGallery.tsx @@ -1,4 +1,5 @@ import { useState } from "react"; +import { packageInstallPreview, packagedExecution } from "@/lib/marketplace/package-execution"; import { FileCode2, Play, Terminal } from "lucide-react"; import type { LucideIcon } from "lucide-react"; import type { Package } from "@/data/packages"; @@ -25,31 +26,23 @@ export function PackageGallery({ pkg, gatewayUrl }: { pkg: Package; gatewayUrl: const frames: Frame[] = [ { id: "install", - label: "Install", + label: packagedExecution(pkg) ? "Evaluated bundle" : "Install", icon: Terminal, filename: "terminal", tone: "terminal", - body: [ - `$ npx super-agent install ${pkg.id}`, - "", - `→ resolving ${pkg.id}@${pkg.latest}`, - `→ runtimes ......... ${pkg.compatibility.map((c) => c.runtime).join(", ") || "any MCP client"}`, - `→ scopes ........... ${pkg.scopes.join(", ") || "none"}`, - `→ size ............. ${pkg.size}`, - "", - `✓ ${pkg.name} is available to your agent`, - "", - "# or point any MCP client at the gateway:", - `# ${gatewayUrl}`, - ].join("\n"), + body: packageInstallPreview(pkg, gatewayUrl), }, ...(pkg.systemPrompt ? [ { id: "prompt", - label: "System prompt", + label: + packagedExecution(pkg)?.kind === "source-state" ? "Workflow source" : "System prompt", icon: FileCode2, - filename: `${pkg.id}.system-prompt.md`, + filename: + packagedExecution(pkg)?.kind === "source-state" + ? `${pkg.id}.workflow.yaml` + : `${pkg.id}.system-prompt.md`, tone: "editor" as const, body: pkg.systemPrompt.split("\n").slice(0, 26).join("\n"), }, diff --git a/src/components/marketplace/PackagedExecutionInstructions.tsx b/src/components/marketplace/PackagedExecutionInstructions.tsx new file mode 100644 index 00000000..2fec2693 --- /dev/null +++ b/src/components/marketplace/PackagedExecutionInstructions.tsx @@ -0,0 +1,88 @@ +import type { Package } from "@/data/packages"; +import { packagedExecution } from "@/lib/marketplace/package-execution"; +export function PackagedExecutionInstructions({ + pkg, + compact = false, +}: { + pkg: Package; + compact?: boolean; +}) { + const execution = packagedExecution(pkg); + if (!execution) return null; + return ( +
+

Use the evaluated bundle

+

+ Version {pkg.latest} was evaluated with its packaged runner and the environment below. + Connecting an MCP client or copying the prompt does not reproduce that execution. +

+ + {execution.runtime} + + + Download evaluated ZIP v{pkg.latest} + +

+ Verify archive integrity with the{" "} + + signature sidecar + {" "} + and{" "} + + public key + + . +

+ {compact ? ( +

+ + Read the setup instructions + {" "} + before running the bundle. +

+ ) : ( + <> +
    +
  1. + Unpack the ZIP and follow{" "} + + {pkg.id}/skills/{pkg.id}/SKILL.md + + . +
  2. +
  3. + Keep the included runtime profile, dependencies and exact model version. Other models + and environments remain unqualified. +
  4. + {execution.kind === "source-state" ? ( +
  5. + Configure TYPESAFE_API_KEY privately in your local environment. The + runner sends authorized input fields to TypeSafe only with explicit source-upload + consent. Use the bundled instructions to configure the pinned Node host and, where + required, the XML reader. +
  6. + ) : ( +
  7. + Use the exact cached local model and packaged runner specified in the bundle. A + prompt pasted into another assistant has no inherited qualification. +
  8. + )} +
+

+ The evaluation covers source-grounded preparation. Financial actions, external sending, + real security tests and release approval require separate authorized evidence. +

+ + )} +
+ ); +} diff --git a/src/lib/marketplace/detail.functions.ts b/src/lib/marketplace/detail.functions.ts index 04a06fbb..7c33a79a 100644 --- a/src/lib/marketplace/detail.functions.ts +++ b/src/lib/marketplace/detail.functions.ts @@ -1,4 +1,5 @@ import { createServerFn } from "@tanstack/react-start"; +import { loadPublicEvaluationCompatibility } from "@/lib/plugins/public-compatibility-loader.server"; import { supabaseAdmin as _supabaseAdmin } from "@/integrations/supabase/client.server"; const supabaseAdmin = _supabaseAdmin; import { createTtlCache } from "@/lib/cache/ttl-cache"; @@ -70,13 +71,14 @@ export const getPackageDetail = createServerFn({ method: "GET" }) const { data: versions } = await supabaseAdmin .from("package_versions") .select( - "version, status, notes, created_at, examples, compatibility, rules, permissions, system_prompt", + "id, version, status, notes, created_at, examples, compatibility, rules, permissions, system_prompt", ) .eq("package_id", pkg.id) .order("created_at", { ascending: false }); const vers = versions ?? []; - const latest = vers.find((v) => v.version === pkg.latest_version) ?? vers[0]; + const latest = vers.find((v) => v.version === pkg.latest_version); + if (!latest) return null; const versionList: PackageVersion[] = vers.map((v) => ({ version: v.version, @@ -85,7 +87,11 @@ export const getPackageDetail = createServerFn({ method: "GET" }) notes: (v.notes as string) ?? "", })); - const compatibility = latest ? normCompat(latest.compatibility) : []; + const [compatibilityData, { data: rs }] = await Promise.all([ + loadPublicEvaluationCompatibility(pkg.id, latest), + supabaseAdmin.from("reviews").select("rating").eq("package_id", pkg.id), + ]); + const compatibility = normCompat(compatibilityData); const examples = latest ? normExamples(latest.examples) : []; const rules = (latest?.rules ?? {}) as Record; const versionPerms = asArr(latest?.permissions).filter( @@ -95,10 +101,6 @@ export const getPackageDetail = createServerFn({ method: "GET" }) const scopes = versionPerms.length ? versionPerms : pkgScopes; // ratings + reviews count via reviews aggregate - const { data: rs } = await supabaseAdmin - .from("reviews") - .select("rating") - .eq("package_id", pkg.id); const reviewCount = rs?.length ?? 0; const ratingAvg = reviewCount > 0 diff --git a/src/lib/marketplace/package-execution.ts b/src/lib/marketplace/package-execution.ts new file mode 100644 index 00000000..7bc829e5 --- /dev/null +++ b/src/lib/marketplace/package-execution.ts @@ -0,0 +1,52 @@ +import type { Package } from "../../data/packages.ts"; +import { agentPluginZipUrl } from "../skills/open-skills.ts"; +export function packagedExecution(pkg: Pick) { + const supported = pkg.compatibility.filter((c) => c.status === "supported"); + const source = supported.find((c) => + /^typesafe\/[^/]+\/[^/]*-source-state-v\d+@node-/.test(c.runtime), + ); + const local = supported.find( + (c) => + c.runtime.startsWith("mlx-community/") && c.runtime.endsWith("/redact-route-generate-v1"), + ); + const target = source ?? local; + return target + ? { + kind: source ? ("source-state" as const) : ("local-model" as const), + runtime: target.runtime, + zipUrl: agentPluginZipUrl(pkg.id), + version: pkg.latest, + } + : null; +} +export function packageInstallPreview(pkg: Package, gatewayUrl: string) { + const execution = packagedExecution(pkg); + if (execution) + return [ + "# Download the complete evaluated bundle:", + `curl -fL ${execution.zipUrl} -o ${pkg.id}.zip`, + `# Version: ${pkg.latest}`, + `# Evaluated runtime: ${execution.runtime}`, + `# Unpack and follow ${pkg.id}/skills/${pkg.id}/SKILL.md.`, + "# Keep its runtime profile and explicit source-upload consent.", + "# Prompt copying or MCP access alone is not this evaluated execution.", + ].join("\n"); + return [ + `$ npx super-agent install ${pkg.id}`, + "", + `→ resolving ${pkg.id}@${pkg.latest}`, + `→ runtimes ......... ${ + pkg.compatibility + .filter((c) => c.status === "supported") + .map((c) => c.runtime) + .join(", ") || "No supported runtime declared" + }`, + `→ scopes ........... ${pkg.scopes.join(", ") || "none"}`, + `→ size ............. ${pkg.size}`, + "", + `✓ ${pkg.name} is available to your agent`, + "", + "# MCP transport endpoint:", + `# ${gatewayUrl}`, + ].join("\n"); +} diff --git a/src/lib/plugins/public-compatibility-loader.server.ts b/src/lib/plugins/public-compatibility-loader.server.ts new file mode 100644 index 00000000..1456d387 --- /dev/null +++ b/src/lib/plugins/public-compatibility-loader.server.ts @@ -0,0 +1,45 @@ +/** Shared read-only evidence loader for public metadata and marketplace pages. */ +import { createHash } from "node:crypto"; +import { supabaseAdmin } from "@/integrations/supabase/client.server"; +import { publicCompatibility } from "./public-compatibility.server"; +export async function loadPublicEvaluationCompatibility( + packageId: string, + version: { + id: string; + version: string; + system_prompt: string; + compatibility: unknown; + }, +): Promise { + const [compat, latestRun, artifact] = await Promise.all([ + supabaseAdmin + .from("skill_compatibility") + .select("package_id,version,model,status,pass_rate,total_cases,passed_cases") + .eq("package_id", packageId) + .eq("version", version.version), + supabaseAdmin + .from("adversarial_runs") + .select( + "package_id,version_id,model,total,passed,failed,pass_rate,severity_weighted_score,by_severity,outcomes", + ) + .eq("package_id", packageId) + .eq("version_id", version.id) + .order("created_at", { ascending: false }) + .limit(1) + .maybeSingle(), + supabaseAdmin + .from("package_artifacts") + .select("sha256") + .eq("version_id", version.id) + .maybeSingle(), + ]); + return !compat.error && !latestRun.error && !artifact.error && artifact.data + ? publicCompatibility(version.compatibility, compat.data, latestRun.data, { + packageId, + versionId: version.id, + version: version.version, + promptSha256: createHash("sha256").update(version.system_prompt).digest("hex"), + archiveSha256: artifact.data.sha256, + }) + : (version.compatibility ?? []); +} diff --git a/src/routes/api/public/packages.$slug.ts b/src/routes/api/public/packages.$slug.ts index 449bbb12..9e281bf3 100644 --- a/src/routes/api/public/packages.$slug.ts +++ b/src/routes/api/public/packages.$slug.ts @@ -1,6 +1,5 @@ import { createFileRoute } from "@tanstack/react-router"; -import { createHash } from "node:crypto"; -import { publicCompatibility } from "@/lib/plugins/public-compatibility.server"; +import { loadPublicEvaluationCompatibility } from "@/lib/plugins/public-compatibility-loader.server"; import { supabaseAdmin as _supabaseAdmin } from "@/integrations/supabase/client.server"; const supabaseAdmin = _supabaseAdmin; @@ -47,40 +46,7 @@ export const Route = createFileRoute("/api/public/packages/$slug")({ .eq("version", pkg.latest_version) .maybeSingle(); - const [compat, latestRun, artifact] = ver - ? await Promise.all([ - supabaseAdmin - .from("skill_compatibility") - .select("package_id,version,model,status,pass_rate,total_cases,passed_cases") - .eq("package_id", pkg.id) - .eq("version", ver.version), - supabaseAdmin - .from("adversarial_runs") - .select( - "package_id,version_id,model,total,passed,failed,pass_rate,severity_weighted_score,by_severity,outcomes", - ) - .eq("package_id", pkg.id) - .eq("version_id", ver.id) - .order("created_at", { ascending: false }) - .limit(1) - .maybeSingle(), - supabaseAdmin - .from("package_artifacts") - .select("sha256") - .eq("version_id", ver.id) - .maybeSingle(), - ]) - : []; - const scopedCompatibility = - ver && !compat?.error && !latestRun?.error && !artifact?.error && artifact?.data - ? publicCompatibility(ver.compatibility, compat?.data, latestRun?.data, { - packageId: pkg.id, - versionId: ver.id, - version: ver.version, - promptSha256: createHash("sha256").update(ver.system_prompt).digest("hex"), - archiveSha256: artifact.data.sha256, - }) - : (ver?.compatibility ?? []); + const scopedCompatibility = ver ? await loadPublicEvaluationCompatibility(pkg.id, ver) : []; const { id: _omit, is_published: _p, review_status: _r, ...rest } = pkg; return new Response( JSON.stringify({ diff --git a/src/routes/marketplace.$packageId.tsx b/src/routes/marketplace.$packageId.tsx index 8615f987..6ecf916a 100644 --- a/src/routes/marketplace.$packageId.tsx +++ b/src/routes/marketplace.$packageId.tsx @@ -25,6 +25,8 @@ import { BookOpen, Bot, Gauge, KeyRound, PackageIcon, ShieldCheck, Star, Tag } f import { useEffect, useState } from "react"; import { ShareOnXButton } from "@/components/share/ShareOnXButton"; import { PackageGallery } from "@/components/marketplace/PackageGallery"; +import { PackagedExecutionInstructions } from "@/components/marketplace/PackagedExecutionInstructions"; +import { packagedExecution } from "@/lib/marketplace/package-execution"; import { StatLine } from "@/components/marketplace/StatLine"; import { AGENT_PLUGINS_SITE, @@ -103,6 +105,7 @@ const SECTIONS = [ function PackageDetail() { const { pkg } = Route.useLoaderData(); + const execution = packagedExecution(pkg); const { user } = useAuth(); const requireAuth = useRequireAuth(); const [selectedVersion, setSelectedVersion] = useState(pkg.latest); @@ -300,9 +303,13 @@ function PackageDetail() {
-

System prompt

+

+ {execution ? "Package source (inspection)" : "System prompt"} +

- The exact instructions this package installs into your agent. + {execution + ? "Inspect the source here. The complete evaluated execution requires the bundled runner and runtime profile." + : "The exact instructions this package installs into your agent."}

@@ -346,7 +353,11 @@ function PackageDetail() {
@@ -354,7 +365,7 @@ function PackageDetail() {
@@ -374,118 +385,130 @@ function PackageDetail() {