SINT Protocol Documentation Audit
SINT Protocol ships a serious-looking governance stack — a self-declared canonical FACTS page, an RFC-2119 spec, a quickstart, an API reference, SDKs, and a deployment guide — but the surfaces openly disagree with each other on the numbers that matter most: what tier a physical action is, what fields and identifiers the API takes, how many packages and bridges exist, and how the core escalation math resolves. For a protocol whose entire pitch is "the layer between an agent's decision and its irreversible consequence," the documentation's internal contradictions are themselves the safety risk.
1. Robot motion is classified T1, T2, and T3 across pages — and the Tiers page contradicts itself (critical)
Location: /protocol/tiers, /architecture, /products/os, /quickstart, /developers/api-reference
Problem: The protocol computes effective tier = max(base, Δ_human, Δ_trust, Δ_env, Δ_novelty), so a low base tier can resolve upward. But the docs disagree at the base level, where deltas can't explain it away:
- The Tiers table lists "Move a robot / publish
/cmd_vel" as T2 — Act, Requires review. - The Architecture page classifies "move the robot two meters forward" (
nodes.invoke("move_forward")) as "T3 — physical, irreversible … T3 requires human approval." - The SINT OS page's tier table also places
nodes.invokein T3 — Physical / irreversible.
So robot actuation is T2 on one canonical page and T3 on two others — a base-classification disagreement, not a deltas artifact.
Worse, the Tiers page contradicts itself. Its table says a robot move is T2, but its own worked example reads: "A warehouse robot with base tier T1 proposes a nav2.move_to_pose action … Effective tier max(1,0,0,0,0) = 1. Auto-approved, audited." A robot move is simultaneously a T2 table entry and a base-T1, auto-approved example on the same page. The Quickstart and API reference both then return "tier": "T1" for a cmd_vel publish, consistent with the example but not the table.
Consequence: This is the product's central promise — graduated human oversight of physical actuation. A developer or agent who trusts the Quickstart/API-reference/worked-example path will auto-approve robot motion that the Architecture and OS pages say requires human approval, and that the Tiers table says requires review. Even granting base-vs-effective semantics, a reader cannot determine the base tier of robot actuation because three pages assign three values.
The fix: Pick one canonical base tier for robot actuation (cmd_vel / nodes.invoke / move_to_pose) and put it on the FACTS page. Make the Tiers table, Architecture, and OS pages agree on it. In every tier example, show the max(base, Δ…) arithmetic inline so an auto-approved T1 result is visibly a computed effective tier, not the default classification of moving a robot.
2. Quickstart, API reference, and spec disagree on field names — and on whether budget is a number or an object (critical)
Location: /quickstart vs /developers/api-reference vs /protocol/spec
Problem: The three request/response shapes don't match on names or types.
Names: Quickstart sends agentId, physicalContext, estimatedVelocity_ms; the API reference sends agentDID, contextSnapshot, sensorHealth. The agent identifier is agentId (quickstart) vs agentDID (API ref and spec).
The response budget field is worse than a rename — it changes type. Quickstart returns "budget_ms": 2000 (a scalar number). The API reference returns "budget": { "maxDuration_ms": 2000, "interruptible": true } (an object). The spec calls the same field executionBudget: { maxDuration_ms, interruptible } (also an object). So one field is named three ways and is a number in one place and a structured object in two others.
Consequence: An agent or developer extracting the Quickstart curl block cannot run it against a gateway that follows the API reference — the field names won't bind. The budget type mismatch is the harder break: a generated client that reads budget_ms as an integer will fail to deserialize the budget/executionBudget object the contract actually returns, and there is no "use your judgment" fallback for a machine. The onboarding example is wrong relative to the reference it's meant to teach.
The fix: Normalize on the spec's field names (agentDID, contextSnapshot, sensorHealth, executionBudget) and the object shape { maxDuration_ms, interruptible } across Quickstart and API reference, and publish one request/response JSON schema both pages link to.
3. The DID identifier uses two different DID methods across examples and the normative schema (significant)
Location: /protocol/spec §1.1 vs /quickstart, /developers/api-reference
Problem: The spec's token schema models the agent identifier as "agentDID": "did:sint:agent:<sha256-fingerprint>" and §1.1 states agentDID "MUST use W3C DID Core 1.0." Both the Quickstart ("agentId": "did:key:z6MkExample") and the API reference ("agentDID": "did:key:z6Mk...") use the did:key method instead of did:sint:agent.
Consequence: This is distinct from the name drift in Finding 2 — it's a value-format drift. A developer or agent following the examples will mint and submit did:key:… identifiers, while the normative schema models did:sint:agent:<sha256>. If the gateway validates against the spec's method, every example identifier is non-conformant; if it accepts did:key, the spec's schema is misleading. Either way an implementer can't tell which DID method is canonical.
The fix: Decide the canonical DID method, show it identically in the spec schema and both examples, and if both did:key and did:sint:agent are valid, state that explicitly in §1.1.
4. The canonical onboarding token violates the spec's own MUST-reject rule (critical)
Location: /quickstart vs /protocol/spec §1.1
Problem: Spec §1.1 states: "MUST reject tokens with tier ≥ 1 and physicalConstraints.eStopBinding == null." The Quickstart's token-issuance example sets physicalConstraints: { maxLinearVelocity_ms: 1.0 } with no eStopBinding, then uses that token to authorize a cmd_vel action that resolves to T1.
Consequence: The first token a developer is taught to mint is one a spec-conformant gateway MUST refuse. Either the reference gateway doesn't enforce its own normative MUST (a conformance hole), or the Quickstart teaches a request that will 4xx in production. An agent generating tokens from the Quickstart template will produce non-conformant tokens by default.
The fix: Add eStopBinding (e.g. "topic"/"service"/"action") to the Quickstart token, and add a troubleshooting note that tier ≥ 1 tokens without an e-stop binding are rejected by design.
5. The trust-score worked example contradicts its own Δ_trust table, and the table inverts the risk direction (critical)
Location: /protocol/tiers
Problem: The Δ_trust band table states Δ_trust = 3 if CSML < 0.30. The worked example on the same page computes, for GPT-5.2, "CSML … reads 0.16 → 0." Since 0.16 < 0.30, the table says Δ_trust should be 3, not 0. Separately, the band's direction is inverted relative to the CSML risk labels: the CSML calibration table marks low scores (GPT-5.2 = 0.16, Opus = 0.21) as "Low" risk, yet the band assigns the highest trust penalty (Δ_trust = 3) to the lowest CSML.
Consequence: This is the core escalation arithmetic. As written, the table would escalate the safest model (lowest CSML) the most, and the worked example silently uses a different rule than the table beside it. An implementer who codes the published bands will systematically over-escalate safe backends and under-escalate risky ones — a direct inversion of the protocol's stated correction behavior, with no way to tell whether the table or the example encodes the real gateway logic.
The fix: Reconcile the band table with the worked example and the CSML risk semantics — almost certainly the band should escalate on high CSML — and re-derive the worked example so its 0.16 → 0 step matches the published bands.
6. CSML expands to three different things, and the README's expansion contradicts its own formula (significant)
Location: /protocol/csml and /facts vs github README (#csml-latency)
Problem: The FACTS page and CSML page define CSML as "Composite Safety-Model-Ledger." The GitHub README heads its section "CSML: Composite Safety-Model Latency." The CSML page also notes a third, deprecated expansion: "Continuous Safety Monitoring Language." The README's "Latency" expansion is self-refuting: its own formula keeps the + ε·𝟙[ledger_intact(t)] term — the "L" is the ledger integrity indicator, not latency.
Consequence: CSML drives automatic tier escalation. The formula is identical across every surface (same α/β/γ/δ/ε terms and ledger_intact indicator), so the gateway computes the same quantity regardless — which is why this is a naming defect, not a math defect. But a reader encountering three expansions, one self-contradicted by its own equation, cannot be confident the README's metric is the same as the spec's, and may cite or document the wrong name.
The fix: Per the FACTS update policy, propagate "Composite Safety-Model-Ledger" to the README and delete the "Latency" expansion. The changelog already claims this was "locked" in v0.2 — finish the propagation so the README matches.
7. CSML = 0.66 yields Δ_trust = 1 on the Tiers page but Δ_trust = 2 on the CSML page (significant)
Location: /protocol/csml vs /protocol/tiers
Problem: The CSML page states "Llama 4 Maverick with CSML = 0.66 triggers Δ_trust = 2, automatically elevating any T0 request to T2." The Tiers page band places 0.66 in 0.60 ≤ CSML < 0.80 → Δ_trust = 1.
Consequence: Two pages compute different escalation outcomes from the same input. Under the CSML page a high-risk model's read-only request jumps to T2 (review); under the Tiers page it only gets +1. The protocol's automatic-correction guarantee resolves differently depending on which page you implement.
The fix: Fix the band boundaries so 0.66 maps to a single Δ_trust, and reference one shared Δ_trust table from both pages rather than restating it.
8. Security vulnerability reporting ships with a placeholder PGP fingerprint (significant)
Location: /legal/security
Problem: The security policy offers encrypted disclosure but the PGP key fingerprint is a literal unfilled placeholder: "fingerprint: <TBD, to be published>." The hall-of-fame/acknowledgments page it links is also "to be created."
Consequence: A researcher who wants to encrypt a vulnerability report for a physical-AI governance protocol has no key to encrypt to. Encryption is explicitly optional ("You can encrypt your email") and a working email channel exists, so disclosure is not fully blocked — but the one piece of the security flow that must be concrete before launch is unfinished in production, and on a safety/governance product that signals the policy was published before it was ready.
The fix: Publish the real PGP fingerprint (or remove the encryption offer until a key exists), and either stand up the acknowledgments page or drop the link until there's content.
9. The README flow diagram invents a DENY decision the enum doesn't have (significant)
Location: github README vs /protocol/spec §2.2
Problem: The normative spec defines the decision enum as ALLOW | BLOCK | ESCALATE | DEFER — there is no DENY. The README's flow diagram reads "Agent ──► SINT Bridge ──► Policy Gateway ──► Allow / Deny / Escalate," presenting "Deny" in the slot where a returned decision value belongs, alongside the real values Allow and Escalate.
Consequence: An agent or integrator parsing the README flow will look for a DENY decision value the gateway never returns, and may miss that the real "no" path is BLOCK (plus DEFER). (Note: the Architecture and OS "Denies" columns describe what a cross-system policy blocks — a policy-effect verb, not a return value — and the spec itself uses "deny" as a verb in /v1/approvals/:id/resolve → "Approve or deny." Those usages are defensible; the README diagram is the one that presents Deny as a decision value.)
The fix: In the README flow diagram, replace "Deny" with the spec's actual decision values (Allow / Block / Escalate / Defer), so the diagram matches the PolicyDecision enum.
10. Package and bridge counts contradict the "single source of truth" (significant)
Location: /facts vs github README
Problem: FACTS declares itself canonical ("if you find a discrepancy … this page wins") and states 41 packages and 12 transport bridges. The README says "Total: 49 repo packages" and heads a section "Bridges (15 bridges)" — while the same README's comparison table says "✅ 12 bridges." So the README disagrees with FACTS (41 vs 49, 12 vs 15) and with itself (15 vs 12). The 15-bridge heading then lists 9 + 2 + 3 = 14 entries.
Consequence: Anyone sizing the project or auditing the bridge surface gets a different answer from every artifact. For a protocol selling completeness ("twelve transport bridges"), the headline inventory numbers don't reconcile across its own front door.
The fix: Run the FACTS-page propagation that's already documented (FACTS → WHITEPAPER → README → site). Make the README derive its counts from FACTS, and fix the README's internal 15-vs-12-vs-14 mismatch.
11. Bridge inventories don't list the same bridges (significant)
Location: /facts vs github README
Problem: Beyond the count, the contents disagree. The FACTS 12-bridge list includes "HAL" but no Home Assistant bridge. The README's bridge inventory includes @sint/bridge-homeassistant ("Consumer & Health") which is absent from the FACTS list, and shows no obvious "HAL" entry.
Consequence: A developer checking whether their transport (e.g. Home Assistant) is supported gets "yes" from the README and "no" from the canonical page. The supported-integrations matrix — a primary reason to adopt a bridge-based protocol — is unreliable.
The fix: Publish one authoritative bridge table on FACTS with exact package names, and have the README and OS page reference it rather than maintain parallel lists.
12. The "out-of-policy spread" headline figure is 4.8× on one page and 3.4× everywhere else (significant)
Location: /introduction vs /protocol/whitepaper, /protocol/csml
Problem: The introduction states identical commands across four frontier models produce "up to a 4.8× spread in out-of-policy attempts." The whitepaper and CSML page both cite "a 3.4× spread in prompt-level out-of-policy attempt rates."
Consequence: This is the motivating statistic for the entire protocol — the empirical justification quoted in the abstract. A 4.8× vs 3.4× discrepancy on the headline number undercuts the credibility of the research framing and leaves readers unsure which figure the whitepaper actually supports.
The fix: Decide the correct figure, add it to FACTS as a canonical number, and align the intro with the whitepaper/CSML pages (or explain why the intro's "up to" bound differs).
13. Gateway port is 3100 in two places and 4100 in the SINT OS boot example (significant)
Location: /products/os vs /quickstart, /developers/deployment
Problem: The Quickstart (http://localhost:3100) and the Deployment Docker Compose ("3100:3100") both run the gateway on port 3100. The SINT OS boot example sets gatewayUrl: "http://localhost:4100". The OS page also points the avatar at serverUrl: "http://localhost:3005", a port documented nowhere else.
Consequence: A developer who copies the SintOS boot config will point the SDK at port 4100 while their gateway (started per the Quickstart/Deployment docs) listens on 3100 — a connection failure with no obvious cause, since both pages look authoritative.
The fix: Standardize the gateway port across all examples (the Deployment/Quickstart 3100 appears canonical), and document the avatar server port (3005) where the avatar component is configured.
14. The SDK page promises "full coverage" then prints a matrix full of gaps (significant)
Location: /developers/sdks
Problem: The SDK page opens with "All SDKs wrap the same HTTP/SSE gateway API and cover the full protocol surface," then its own coverage matrix shows Rust lacks batch intercept, Go and Rust lack CSML read, and only TypeScript has OpenClaw integration. The same page also labels Python/Go/Rust "beta … may have breaking changes until v1.0," directly beneath the "full coverage" lead-in.
Consequence: A team picking Rust or Go for its safety stack on the strength of "full coverage" will discover mid-build that CSML reads (the escalation metric) aren't available, and that the SDK may break before v1.0. The lead-in claim directly contradicts the table beneath it.
The fix: Drop "cover the full protocol surface" and let the matrix and the beta note speak for themselves, so the four SDKs aren't presented as equivalent.
15. The "single source of truth" mechanism is documented but not executed (significant)
Location: /facts, /changelog vs github README
Problem: FACTS describes a strict propagation order (FACTS → WHITEPAPER → README → site → marketing → social) and asserts "This page is updated before any other surface." The changelog goes further, claiming prior inconsistencies are now "aligned": the MIT→Apache-2.0 license and the CSML name ("locked as Composite Safety-Model-Ledger"). Yet the README still carries the unaligned versions — CSML as "Latency," 49 packages, 15 bridges.
Consequence: The credibility of the entire docs set rests on FACTS being authoritative and propagated. When the changelog says "aligned" but the most-read artifact (the GitHub README) still shows the old CSML name, readers learn the canonical-source guarantee is aspirational — which undermines trust in every number FACTS publishes.
The fix: Treat propagation as a release gate: a CI check that fails the build when the README/whitepaper disagree with FACTS on version, package count, bridge count, and CSML definition. Don't mark items "aligned" in the changelog until that check passes.
16. API reference and spec disagree on which endpoints exist (minor)
Location: /developers/api-reference vs /protocol/spec §7
Problem: The API reference documents GET /v1/ready and GET /v1/approvals/ws (WebSocket), neither of which appears in the spec's §7 endpoint table. Conversely, the spec's table lists endpoints (batch intercept, delegate, revoke, ledger query/verify, tier-crosswalk, etc.) that the API reference never covers.
Consequence: An agent building a client from the spec's endpoint table will miss the readiness probe and the WebSocket approval stream; one building from the API reference will miss delegation, revocation, and ledger verification. Neither page is a complete contract on its own.
The fix: Generate both surfaces from the /v1/openapi.json the spec already advertises, so the endpoint set is identical and machine-discoverable.
17. Architecture claims 32 gateway endpoints; spec enumerates ~15 (minor)
Location: /architecture vs /protocol/spec §7
Problem: The Architecture diagram annotates "Policy Gateway (32 endpoints)." The spec's §7 endpoint table enumerates 15, and the API reference describes a small subset.
Consequence: The "32" can't be reconciled against any enumerated list, so a reader can't tell whether half the surface is undocumented or the number is stale.
The fix: Replace the hardcoded "32" with a count derived from the OpenAPI document, or enumerate the additional endpoints.
18. Safety-critical operational procedures are referenced but not present in the docs (minor)
Location: /developers/deployment
Problem: The deployment guide repeatedly defers to repo files not on the documentation site: docs/operations/key-rotation.md, docs/operations/tee-setup.md, and docs/operations/upgrade-guide.md. Key rotation is framed as safety-critical — "If it's lost, every token issued by the gateway becomes unverifiable. Rotate only through the documented key-rotation procedure (see docs/operations/key-rotation.md)."
Consequence: The one procedure an operator must not improvise — rotating the gateway signing key — points to a path that isn't in the published docs. If the file is missing or out of date, an operator who loses or must rotate the key has no authoritative steps.
The fix: Publish the key-rotation, TEE-setup, and upgrade procedures on docs.sint.gg (or link the exact repo URLs and verify they resolve), since they're production-blocking operations.
19. The legal entity (PSHKV Inc) is invisible until the licenses page (minor)
Location: /legal/licenses vs site-wide branding and /protocol/whitepaper
Problem: Every surface attributes the work to "SINT Labs," and the whitepaper citation lists institution = {SINT Labs}, but the trademark/licenses page reveals the marks are owned by PSHKV Inc — a legal entity named nowhere else.
Consequence: For anyone doing license, contributor-agreement, or procurement due diligence, the operating/legal entity behind "SINT Labs" only surfaces in a trademark line. It's a small but real gap between the brand and the legal owner.
The fix: Note the legal entity (PSHKV Inc, d/b/a SINT Labs) once on the FACTS or licenses page and, ideally, in the whitepaper citation, so attribution and ownership are unambiguous.
What they do well
- A canonical FACTS page is the right idea — declaring one source of truth with an explicit propagation order and "this page wins" tiebreaker is better governance than most projects attempt; the failure is execution, not concept.
- The spec is genuinely normative — RFC-2119 MUST language, a typed token schema, a
PolicyDecisionenum, and a 15-row endpoint table give implementers a real contract to build against. - Honest changelog of breaking changes — the v0.2 entry openly records the T1–T5→T0–T3 consolidation, the MIT→Apache-2.0 correction, and the CSML rename, with migration warnings.
Top 3 recommendations
- Make the tier classification of physical actions unambiguous and consistent. Resolve the T1/T2/T3 split for robot motion across Quickstart, API reference, Tiers, Architecture, and OS — including the Tiers page's own table-vs-worked-example conflict — and fix the inverted Δ_trust band so the safest model isn't escalated the most. This is the product's core safety claim and currently contradicts itself.
- Generate examples and references from one schema/OpenAPI source. Field-name drift (
agentId/agentDID), thebudgetscalar-vs-object mismatch, thedid:key-vs-did:sint:agentmethod drift, the missing-eStopBindingtoken, port 3100-vs-4100, and the divergent endpoint lists are all symptoms of hand-maintained parallel copies. A single generated source fixes them at once and makes the docs agent-parseable. - Enforce FACTS propagation as a CI gate. Block releases when the README/whitepaper disagree with FACTS on version, package count, bridge inventory, CSML definition, and the headline spread figure — and only then mark them "aligned" in the changelog.