Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .codex/skills/tangle-blog-editor/references/rewrite-rubric.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Score each dimension 1-5.
| Style | Research-note template | Builder voice with varied structure |
| Conversion | No next action | Specific install, curl, manifest, CTA, or decision |
| Evidence | Unsupported claims | Primary sources, internal links, proof blocks |
| Presentation | Markdown scaffolding only | Artifact, diagram, table, screenshot, trace, or designed cover supports the argument |

## Rewrite Pass Order

Expand All @@ -21,6 +22,7 @@ Score each dimension 1-5.
5. Retrieval: add answer capsule, comparison table, and FAQ where useful.
6. Tangle: move specific product mechanism earlier.
7. Ending: replace summary with decision or readiness test.
8. Presentation: add or preserve a real artifact when the post is long, code-heavy, or abstract.

## Existing Series Diagnosis

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@

Tangle blog posts should read like a senior builder explaining infrastructure they have used, shipped, or verified.

Blog is a broad surface.
It can carry technical explainers, product essays, comparisons, launch notes, field reports, research threads, and posts about anything Tangle has done.
Do not force every post into "technical deep dive" voice.

The target blend:

```text
Expand All @@ -23,6 +27,8 @@ concrete builder pressure
- Do not use "The Object Being Optimized", "Evaluation Protocol", "Working Rule", or "Source Trail" as repeated default headings across a series.
- Do not overuse one-sentence paragraphs.
- Do not turn every idea into a table or fenced text block.
- Do not use raw inventory counts as proof of seriousness. A blog index should show reader paths, not "80 posts published".
- Do not use markdown scaffolding as the whole presentation layer. Long posts need at least one artifact: diagram, table, screenshot, trace, code sample, terminal proof, or designed cover.
- Do not write generic "field overview" prose before saying why Tangle, a builder, or an operator cares.
- Do not close with a restated thesis.
- Avoid AI cadence: "It is not X. It is Y.", "The useful question is...", "The serious version is...", "That is why...", "Here's the thing", "Turns out".
Expand Down
9 changes: 9 additions & 0 deletions .codex/skills/tangle-blog-proof/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ When checking an edited/new post, run:
node .codex/skills/tangle-blog-proof/scripts/check-post.mjs src/content/blog/<slug>.mdx
```

When checking the full blog surface, run:

```bash
pnpm check:blog
```

Then run the repo's normal validation when the change is substantive:

```bash
Expand All @@ -36,6 +42,9 @@ The script catches structure, not judgment. Also check:
- Competitor comparisons are fair and based on current primary sources.
- The CTA is specific enough for a builder or agent to act on.
- The post does not end with a summary that merely restates the thesis.
- Blog and research pages do not market raw post counts or other inventory totals.
- Blog index navigation works by series, topic, date, or argument.
- Long posts are not only markdown scaffolding; they carry at least one artifact such as a cover, diagram, table, screenshot, trace, code block, or terminal proof.

## Output

Expand Down
6 changes: 6 additions & 0 deletions .codex/skills/tangle-blog-proof/references/proof-checklist.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
- Direct CTA exists.
- Referenced images exist.
- No obvious AI-cadence banned phrases.
- Blog and research pages do not show vanity inventory counts such as "80 posts published".
- Blog index gives reader paths through series, topics, dates, or arguments.

## Judgment Gates

Expand All @@ -20,6 +22,8 @@
- Limitations are explicit.
- Competitor comparisons are fair and current.
- The ending gives a decision, not a summary.
- Research pages include only work with a claim, model, method, trace/evidence path, or falsifiable argument.
- Blog posts are allowed to be essays, launch notes, field reports, comparisons, or implementation notes; they should not all be forced into one technical deep-dive template.

## Common Fixes

Expand All @@ -29,3 +33,5 @@
- Move Tangle-specific proof above generic background.
- Add FAQ questions that match search intent.
- Replace "What This Gets You" with a concrete CTA.
- Replace raw archive totals with series cards, topic filters, or a date-sorted archive.
- Replace markdown-only stretches with a diagram, table, screenshot, trace, terminal output, or designed cover.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"generate-types": "wrangler types",
"status:collect": "node scripts/collect-status.mjs",
"check:links": "node scripts/check-links.mjs",
"check:blog": "node scripts/audit-blog.mjs",
"check:copy": "node scripts/check-copy.mjs",
"check:models": "node scripts/check-models.mjs",
"audit:visual": "node scripts/visual-audit.mjs"
Expand Down
211 changes: 211 additions & 0 deletions scripts/audit-blog.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
#!/usr/bin/env node
import fs from 'node:fs'
import path from 'node:path'

const root = process.cwd()
const blogDir = path.join(root, 'src/content/blog')
const pagesDir = path.join(root, 'src/pages')
const json = process.argv.includes('--json')

const bannedPhrases = [
'delve',
'comprehensive',
'facilitate',
'utilizing',
'moreover',
'furthermore',
'landscape',
'crucial',
'paradigm',
"let's dive in",
"here's the thing",
'turns out',
'not just',
'more than just',
'at its core',
]

const repeatedScaffoldHeadings = [
'The Object Being Optimized',
'Evaluation Protocol',
'Working Rule',
'Source Trail',
]

function listFiles(dir, predicate) {
const files = []
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
const full = path.join(dir, entry.name)
if (entry.isDirectory()) files.push(...listFiles(full, predicate))
else if (predicate(full)) files.push(full)
}
return files
}

function parseFrontmatter(text) {
const match = text.match(/^---\n([\s\S]*?)\n---\n/)
if (!match) return { frontmatter: '', body: text, data: {} }

const frontmatter = match[1]
const data = {}
let currentArray = null

for (const line of frontmatter.split('\n')) {
const arrayItem = line.match(/^\s*-\s+(.+)$/)
if (arrayItem && currentArray) {
data[currentArray].push(cleanValue(arrayItem[1]))
continue
}

const pair = line.match(/^([A-Za-z0-9_]+):\s*(.*)$/)
if (!pair) continue

const [, key, rawValue] = pair
currentArray = null

if (!rawValue.trim()) {
data[key] = []
currentArray = key
} else if (/^\d+$/.test(rawValue.trim())) {
data[key] = Number(rawValue.trim())
} else if (rawValue.trim() === 'true' || rawValue.trim() === 'false') {
data[key] = rawValue.trim() === 'true'
} else if (/^\[.*]$/.test(rawValue.trim())) {
data[key] = rawValue
.trim()
.slice(1, -1)
.split(',')
.map((item) => cleanValue(item))
.filter(Boolean)
} else {
data[key] = cleanValue(rawValue)
}
}

return { frontmatter, body: text.slice(match[0].length), data }
}

function cleanValue(value) {
return value.trim().replace(/^['"]|['"]$/g, '')
}

function relativeFile(file) {
return path.relative(root, file)
}

function lineOf(text, needle) {
const index = text.indexOf(needle)
if (index < 0) return 1
return text.slice(0, index).split('\n').length
}

function imageExists(image) {
if (!image?.startsWith('/images/')) return true
return fs.existsSync(path.join(root, 'public', image.slice(1)))
}

function addFinding(findings, severity, file, message, needle, text) {
findings.push({
severity,
file: relativeFile(file),
line: needle && text ? lineOf(text, needle) : 1,
message,
})
}

const postFiles = listFiles(blogDir, (file) => file.endsWith('.mdx')).sort()
const findings = []
const series = new Map()
const tagCounts = new Map()

for (const file of postFiles) {
const text = fs.readFileSync(file, 'utf8')
const { body, data } = parseFrontmatter(text)
const required = ['title', 'slug', 'summary', 'date', 'author', 'tags']

for (const field of required) {
if (data[field] === undefined || data[field] === '') {
addFinding(findings, 'error', file, `Missing frontmatter field: ${field}`)
}
}

if (data.slug && `${data.slug}.mdx` !== path.basename(file)) {
addFinding(findings, 'warning', file, `Slug does not match filename: ${data.slug}`)
}

for (const imageField of ['coverImage', 'heroImage']) {
if (data[imageField] && !imageExists(data[imageField])) {
addFinding(findings, 'error', file, `${imageField} does not exist: ${data[imageField]}`)
}
}

const postSeries = data.series || 'Standalone'
series.set(postSeries, (series.get(postSeries) || 0) + 1)
for (const tag of data.tags || []) tagCounts.set(tag, (tagCounts.get(tag) || 0) + 1)

const hasBodyImage = /!\[[^\]]*]\(\/images\//.test(body) || /<img\b|<figure\b|<picture\b/.test(body)
const hasCode = /```/.test(body)
const hasTable = /^\|.+\|$/m.test(body)
const hasCover = Boolean(data.coverImage || data.heroImage)
if (!hasBodyImage && !hasCode && !hasTable && !hasCover) {
addFinding(findings, 'warning', file, 'No visible artifact: add a cover, diagram, table, code block, or screenshot')
}

const codeBlockCount = (body.match(/```/g) || []).length / 2
if (codeBlockCount >= 5 && !hasBodyImage && !hasTable) {
addFinding(findings, 'warning', file, 'Code-block heavy post without a visual or table artifact')
}

for (const heading of repeatedScaffoldHeadings) {
if (body.includes(`## ${heading}`)) {
addFinding(findings, 'warning', file, `Repeated scaffold heading: ${heading}`, heading, text)
}
}

for (const phrase of bannedPhrases) {
const pattern = new RegExp(`\\b${phrase.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\b`, 'i')
const match = body.match(pattern)
if (match) {
addFinding(findings, 'warning', file, `Weak or AI-cadence phrase: "${phrase}"`, match[0], text)
}
}
}

for (const file of listFiles(pagesDir, (item) => item.endsWith('.astro'))) {
const text = fs.readFileSync(file, 'utf8')
const countPatterns = [
/posts\.length\s*\}\s*published/,
/\b\d+\s+blog posts\b/i,
/\b\d+\s+posts\b/i,
/\bpublished\s+posts\b/i,
]
for (const pattern of countPatterns) {
const match = text.match(pattern)
if (match) {
addFinding(findings, 'error', file, 'Do not market raw blog volume; organize by reader path instead', match[0], text)
}
}
}

const summary = {
posts: postFiles.length,
series: Object.fromEntries([...series.entries()].sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0]))),
tags: Object.fromEntries([...tagCounts.entries()].sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0]))),
errors: findings.filter((finding) => finding.severity === 'error').length,
warnings: findings.filter((finding) => finding.severity === 'warning').length,
findings,
}

if (json) {
console.log(JSON.stringify(summary, null, 2))
} else {
console.log(`Blog audit: ${summary.posts} posts, ${Object.keys(summary.series).length} series, ${summary.errors} errors, ${summary.warnings} warnings`)
console.log('')
for (const finding of findings) {
console.log(`${finding.severity.toUpperCase()} ${finding.file}:${finding.line} - ${finding.message}`)
}
if (findings.length) console.log('')
console.log(summary.errors ? 'NEEDS WORK' : 'PASS')
}

process.exit(summary.errors > 0 ? 1 : 0)
2 changes: 1 addition & 1 deletion src/content/blog/ai-agent-sandbox.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ heroImage: /images/covers/agent-intent-infrastructure.svg
imageAlt: 'Agent runtime diagram showing sandbox files, processes, network policy, snapshots, and evidence'
---

An AI agent sandbox is an isolated runtime where an agent can create files, run processes, call tools, use the network under policy, preserve state, and return evidence. It is not just a code interpreter, browser automation session, or serverless job runner. Tangle Sandbox gives agents a machine-shaped workspace for real work: install dependencies, execute tests, inspect artifacts, recover from failure, and keep the dangerous parts contained. Start with [Tangle Sandbox](https://github.com/tangle-network/tcloud) when the agent needs an environment, not only an API.
An AI agent sandbox is an isolated runtime where an agent can create files, run processes, call tools, use the network under policy, preserve state, and return evidence. A code interpreter, browser automation session, or serverless job runner is too narrow for that job. Tangle Sandbox gives agents a machine-shaped workspace for real work: install dependencies, execute tests, inspect artifacts, recover from failure, and keep the dangerous parts contained. Start with [Tangle Sandbox](https://github.com/tangle-network/tcloud) when the agent needs an environment, not only an API.

The hard part of agent infrastructure is not letting a model produce text. It is giving that model a place to act without handing it your laptop, production credentials, or a shared build server.

Expand Down
2 changes: 1 addition & 1 deletion src/content/blog/blueprint-tee-x402-production-gating.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ pub enum SecretInjectionPolicy {
}
```

The builder enforces this at construction time: any `TeeConfig` with a non-Disabled mode automatically gets `SealedOnly`. Configs deserialized from JSON or TOML go through `validate()` which applies the same check. The reason is not just security hygiene. Env-var injection via container recreation invalidates attestation, breaks sealed secrets, and loses the on-chain deployment ID. A deployed TEE service whose secrets can be changed via environment variable gives up the entire attestation chain.
The builder enforces this at construction time: any `TeeConfig` with a non-Disabled mode automatically gets `SealedOnly`. Configs deserialized from JSON or TOML go through `validate()` which applies the same check. This protects the attestation chain itself. Env-var injection via container recreation invalidates attestation, breaks sealed secrets, and loses the on-chain deployment ID. A deployed TEE service whose secrets can be changed via environment variable gives up the entire attestation chain.

### 6. The blueprint must expose a container source

Expand Down
2 changes: 1 addition & 1 deletion src/content/blog/building-ai-services-on-tangle.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -542,7 +542,7 @@ Full accountability chain.

## What's Next

The final post in this series covers the road ahead: what we're building next, where Tangle fits in the broader landscape, and how to get involved.
The final post in this series covers the road ahead: what we're building next, where Tangle fits in the broader market, and how to get involved.

## FAQ

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ For broader complex returns, crypto should connect to income, business activity,

## Where Tangle Fits

Tangle Tax Agent should produce a review packet, not just a gain/loss number. It should organize wallet files, classify events, flag incomplete history, and prepare draft filing artifacts for review-before-submit. The relevant control model is covered in [Automated Tax Filing With Review Control](/blog/automated-tax-filing-review-before-submit).
Tangle Tax Agent should produce a review packet before any gain/loss number. It should organize wallet files, classify events, flag incomplete history, and prepare draft filing artifacts for review-before-submit. The relevant control model is covered in [Automated Tax Filing With Review Control](/blog/automated-tax-filing-review-before-submit).

## What This Does Not Prove

Expand Down
4 changes: 2 additions & 2 deletions src/content/blog/distributed-training-demo.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ tags:

Distributed training over the open internet usually dies at the sync step. The model can fit on GPUs, the data can be sharded, and the operators can be paid, but the network still has to move training state between machines that do not sit inside one data center. That is the pressure behind DeMo, Decoupled Momentum Optimization: reduce the communication payload enough that permissionless operators can coordinate without pretending they are one tightly coupled cluster.

Tangle's [Training Blueprint](https://github.com/tangle-network/training-blueprint) is the protocol version of that idea. It is not just a research note. It is a service surface where operators join training jobs, synchronize state, submit checkpoints, and get paid or penalized under network rules.
Tangle's [Training Blueprint](https://github.com/tangle-network/training-blueprint) is the protocol version of that idea. It turns the research direction into a service surface where operators join training jobs, synchronize state, submit checkpoints, and get paid or penalized under network rules.

## The Claim

Expand Down Expand Up @@ -117,7 +117,7 @@ That is where Tangle's service graph starts to matter. A model trained through o

This post does not prove every permissionless training job will converge. It does not prove 10,000x lower communication always means lower total cost. It does not prove Tangle has solved dataset quality, adversarial workers, or evaluation capture for every training workload.

It proves a narrower direction: if compressed synchronization makes open-network training viable, the remaining missing piece is not just optimizer code. It is an operator-run service layer with payment, evidence, health checks, and verification.
It proves a narrower direction: if compressed synchronization makes open-network training viable, optimizer code is only one piece. The missing layer is an operator-run service with payment, evidence, health checks, and verification.

## Start

Expand Down
2 changes: 1 addition & 1 deletion src/content/blog/how-tangle-verifies-work.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ The hardest question in decentralized infrastructure isn't "how do we run comput

This post covers what each verification mechanism actually proves, where it breaks down, and how Tangle lets developers wire it all together.

## Why Not Just Use AWS?
## Where Cloud Providers Stop

AWS, Google Cloud, and Azure have decades of production hardening, legal accountability, and compliance certifications. For most applications, they're the right choice.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ With real numbers: suppose an operator could save $5,000 by running a cheaper mo

### How This Compares to Other Accountability Models

Stake-based slashing isn't the only approach to operator accountability, and each alternative makes different tradeoffs. Reputation systems (used by most centralized cloud marketplaces) are cheap and simple, but a malicious operator can build reputation with honest behavior and exploit it later, and reputation scores aren't enforceable on-chain. Escrow models hold payment until delivery confirmation, but they require a trusted arbiter to resolve disputes and don't impose penalties beyond withholding payment, so the operator's downside is capped at the job revenue. Optimistic fraud proofs (used by Optimism and Arbitrum for rollup verification) assume results are correct unless challenged within a window, which is gas-efficient, but detection depends entirely on external watchers submitting challenges in time. Stake-based slashing is more capital-intensive for operators, but it provides the strongest deterrent: the penalty for cheating scales with the operator's total stake, not just the value of one job.
Stake-based slashing isn't the only approach to operator accountability, and each alternative makes different tradeoffs. Reputation systems (used by most centralized cloud marketplaces) are cheap and simple, but a malicious operator can build reputation with honest behavior and exploit it later, and reputation scores aren't enforceable on-chain. Escrow models hold payment until delivery confirmation, but they require a trusted arbiter to resolve disputes and don't impose penalties beyond withholding payment, so the operator's downside is capped at the job revenue. Optimistic fraud proofs (used by Optimism and Arbitrum for rollup verification) assume results are correct unless challenged within a window, which is gas-efficient, but detection depends entirely on external watchers submitting challenges in time. Stake-based slashing is more capital-intensive for operators, but it provides the strongest deterrent: the penalty for cheating scales with the operator's total stake rather than the value of one job.

The combination of technical verification and economic enforcement is more robust than either alone. The known gaps: irrational actors might cheat anyway (which is why verification mechanisms exist as the first line of defense), and subtle quality degradation (serving a slightly worse model, returning slightly stale results) might lower `P(detection)` enough to shift the equation.

Expand Down
Loading
Loading