shibosoftwaredev/f1c100s-linux-nema17-stepper-controller
A four-layer NEMA 17 motor-controller PCB combining an Allwinner F1C100S Linux computer, USB‑PD/buck power system, W5500 Ethernet, STM32 real-time motion control, DRV8825 stepper driver, protection/temperature/current telemetry, USB interfaces, and local LED/buzzer diagnostics.
- Version
- 0.4.56
- License
- unset
- Stars
- 0
scripts/verify-remote-checkpoint.mjs
import fs from "node:fs"
import crypto from "node:crypto"
import assert from "node:assert/strict"
const registry = "https://registry-api.tscircuit.com/"
const packageName = "shibosoftwaredev/f1c100s-linux-nema17-stepper-controller"
const version = "0.4.46-checkpoint-20261019-current-sense"
const manifest = JSON.parse(fs.readFileSync("reports/checkpoint-publish-manifest.json", "utf8"))
const before = JSON.parse(fs.readFileSync("reports/remote-before-checkpoint.json", "utf8")).package
async function request(endpoint, body) {
for (let attempt = 0; attempt < 3; attempt++) {
try {
const response = await fetch(registry + endpoint, {
method: body ? "POST" : "GET",
headers: body ? { "content-type": "application/json" } : undefined,
body: body ? JSON.stringify(body) : undefined,
signal: AbortSignal.timeout(45000),
})
if (!response.ok) throw new Error(`${endpoint}: HTTP ${response.status}`)
return await response.json()
} catch (error) {
if (attempt === 2) throw error
await new Promise(resolve => setTimeout(resolve, 1000))
}
}
}
const release = (await request("package_releases/get", {
package_name_with_version: `${packageName}@${version}`,
})).package_release
assert.equal(release.version, version)
const listing = await request("package_files/list?" + new URLSearchParams({
package_release_id: release.package_release_id,
}))
const byName = new Map(listing.package_files.map(file => [file.file_path, file]))
const checks = []
const pending = [...manifest.files]
async function worker() {
while (pending.length) {
const expected = pending.shift()
const remote = byName.get(expected.file)
if (!remote) {
checks.push({ file: expected.file, error: "missing", match: false })
continue
}
const record = (await request("package_files/get?" + new URLSearchParams({
package_file_id: remote.package_file_id,
}))).package_file
const bytes = record.content_text != null ? Buffer.from(record.content_text)
: Buffer.from(record.content_base64 ?? "", "base64")
const sha256 = crypto.createHash("sha256").update(bytes).digest("hex")
checks.push({ file: expected.file, sha256, match: sha256 === expected.sha256 })
}
}
await Promise.all(Array.from({ length: 4 }, worker))
const after = (await request("packages/get", { name: packageName })).package
const latestUnchanged = before.latest_package_release_id === after.latest_package_release_id &&
before.latest_version === after.latest_version
const report = {
checkedAt: new Date().toISOString(), packageName, version,
releaseId: release.package_release_id,
url: `https://tscircuit.com/${packageName}?version=${version}#3d`,
filesChecked: checks.length, mismatches: checks.filter(check => !check.match),
mainReleaseUnchanged: latestUnchanged, mainVersion: after.latest_version,
mainReleaseId: after.latest_package_release_id,
readyToBuild: release.ready_to_build,
cloudBuild: { completedAt: release.circuit_json_build_completed_at,
error: release.circuit_json_build_error, jobCompletedAt: release.user_code_job_completed_at,
jobError: release.user_code_job_error },
fabricationReady: false,
caveat: "Non-latest draft checkpoint only; unresolved fabrication and hardware qualification remain.",
checks: checks.sort((a, b) => a.file.localeCompare(b.file)),
}
fs.writeFileSync("reports/checkpoint-publish-confirmation.json", JSON.stringify(report, null, 2) + "\n")
assert.deepEqual(report.mismatches, [], "remote checkpoint bytes match local publishing snapshot")
assert.equal(latestUnchanged, true, "main release remains unchanged")
console.log(JSON.stringify({ version, releaseId: report.releaseId, filesChecked: checks.length,
mismatches: report.mismatches.length, mainReleaseUnchanged: latestUnchanged,
mainVersion: report.mainVersion, cloudBuild: report.cloudBuild }, null, 2))