sf-sdk-thesis — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited sf-sdk-thesis (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
npm install @spfunctions/[email protected]
export SF_API_KEY="sf_..." # required — theses are user-scopedcreate → context → signal → evaluate → augment → fork → publish → unpublishimport { SimpleFunctions } from "@spfunctions/sdk"
const sf = new SimpleFunctions({
apiKey: process.env.SF_API_KEY,
baseUrl: process.env.SF_API_URL ?? "https://simplefunctions.dev",
})const theses = await sf.theses.list({
status: "active", // "active" | "killed" | "published" | "all"
limit: 10,
})
console.log(theses.map(t => ({
id: t.id,
title: t.title,
confidence: t.confidence,
status: t.status,
publishedSlug: t.publishedSlug,
})))const thesis = await sf.theses.get("thesis-id")
console.log({
title: thesis.title,
confidence: thesis.confidence,
nodes: thesis.tree?.nodes,
edges: thesis.edges,
recentSignals: thesis.signals?.slice(-5),
})The full causal tree is in thesis.tree. Each node has its own confidence + linked markets.
For programmatic creation, use direct HTTP (SDK wrapper may be deferred per stability classification):
const created = await fetch("https://simplefunctions.dev/api/thesis/create", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.SF_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
text: "Fed cuts rates by July driven by jobs softening + CPI ≤ 2.5%",
}),
}).then(r => r.json())
console.log(created.id, created.tree)The server's LLM classifier rejects shell-escape garbage and expands the thesis into a causal tree. Returns the thesis id.
const signal = await fetch(`https://simplefunctions.dev/api/thesis/${thesisId}/signal`, {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.SF_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
content: "Powell speech: 'job market is softening more than expected'",
source: "news",
}),
}).then(r => r.json())The server appends the signal, schedules the next monitor cycle, and updates affected node confidences.
const evaluation = await fetch(`https://simplefunctions.dev/api/thesis/${thesisId}/evaluate`, {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.SF_API_KEY}`,
"Content-Type": "application/json",
},
}).then(r => r.json())
console.log({
confidenceDelta: evaluation.confidenceDelta,
recommendations: evaluation.positionRecommendations,
killCheck: evaluation.killConditionCheck,
})Uses the heavy evaluation model — expensive, slow. Run periodically (daily, after major signals), not on every minor update.
const heartbeat = await fetch(`https://simplefunctions.dev/api/thesis/${thesisId}/heartbeat`, {
method: "PATCH",
headers: {
"Authorization": `Bearer ${process.env.SF_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
cadence: "1h",
evaluationModelTier: "standard",
monthlyBudgetUsd: 5.00,
killConditions: [
{ type: "node_confidence_below", node: "n1.2", threshold: 0.3 },
{ type: "drawdown_above", percent: 15 },
],
closedLoop: {
entry: false,
exit: false,
},
}),
}).then(r => r.json())See sf-thesis-monitor skill for kill condition types and cadence guidance.
const published = await fetch(`https://simplefunctions.dev/api/thesis/${thesisId}/publish`, {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.SF_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
slug: "fed-rate-cut-july",
}),
}).then(r => r.json())
console.log(published.publishedUrl) // "https://simplefunctions.dev/thesis/fed-rate-cut-july"Slugs are normalized server-side (/[^a-z0-9-]/g strip, max 60 chars).
async function buildAndMonitorThesis(text: string, slug: string) {
// 1. Create
const { id } = await fetch("https://simplefunctions.dev/api/thesis/create", {
method: "POST",
headers: { "Authorization": `Bearer ${process.env.SF_API_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({ text }),
}).then(r => r.json())
// 2. Pull initial tree
const initial = await sf.theses.get(id)
console.log("Initial tree:", initial.tree?.nodes?.length, "nodes")
// 3. Configure heartbeat
await fetch(`https://simplefunctions.dev/api/thesis/${id}/heartbeat`, {
method: "PATCH",
headers: { "Authorization": `Bearer ${process.env.SF_API_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({
cadence: "1h",
evaluationModelTier: "standard",
monthlyBudgetUsd: 5.00,
}),
})
// 4. Publish
const { publishedUrl } = await fetch(`https://simplefunctions.dev/api/thesis/${id}/publish`, {
method: "POST",
headers: { "Authorization": `Bearer ${process.env.SF_API_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({ slug }),
}).then(r => r.json())
return { thesisId: id, publishedUrl }
}
const result = await buildAndMonitorThesis(
"Fed cuts rates by July driven by jobs softening + CPI ≤ 2.5%",
"fed-rate-cut-july"
)
console.log(result)SF_API_KEY matches the user.sf-sdk-quickstart — install + first callsf-thesis-build — CLI workflow for the same lifecyclesf-thesis-monitor — heartbeat config detailssf-sdk-portfolio — intents linked to thesis evaluations~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.