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/test-round9-release-gates.mjs

import fs from "node:fs"
import path from "node:path"
import crypto from "node:crypto"
import assert from "node:assert/strict"
import {spawnSync} from "node:child_process"

const hash=p=>crypto.createHash("sha256").update(fs.readFileSync(p)).digest("hex")
const read=p=>JSON.parse(fs.readFileSync(p,"utf8"))
const circuitSha256=hash("dist/index/circuit.json")
const stock=read("reports/jlcpcb-stock-audit.json")
assert.equal(stock.circuitSha256,circuitSha256)
assert.ok(stock.parts.some(p=>p.status!=="in-stock"),"this test records the actual stock-blocked state; it must be updated if supply recovers")
const metaPath="reports/coil-all-copper-preflight-meta.json"
const original=fs.readFileSync(metaPath),meta=JSON.parse(original)
assert.equal(meta.failureCount,0);assert.equal(meta.circuitSha256,circuitSha256)
const run=()=>spawnSync(process.execPath,["scripts/verify.mjs"],{encoding:"utf8"})
const results=[]
try {
  for(const [name,change,message] of [
    ["independent copper failure",{failureCount:1},"independent copper clearance must pass"],
    ["stale circuit audit",{circuitSha256:"invalid"},"independent copper preflight matches this emitted circuit"],
    ["stale copper geometry",{physicalCopperSha256:"invalid"},"AssertionError"],
  ]){
    fs.writeFileSync(metaPath,JSON.stringify({...meta,...change},null,2)+"\n")
    const test=run();assert.notEqual(test.status,0)
    assert.ok((test.stdout+test.stderr).includes(message),`${name} rejects for its intended reason`)
    results.push({name,failedClosed:true})
  }
}finally{fs.writeFileSync(metaPath,original)}
const actual=run()
assert.notEqual(actual.status,0,"actual full verification is blocked, not passed")
assert.ok((actual.stdout+actual.stderr).includes("all JLCPCB parts cover board quantity"))
results.push({name:"actual final circuit",fullVerificationPassed:false,blockedFor:"JLCPCB orderable stock"})
function manifest(dir){
  if(!fs.existsSync(dir))return {}
  return Object.fromEntries(fs.readdirSync(dir,{recursive:true}).sort()
    .filter(p=>fs.statSync(path.join(dir,p)).isFile()).map(p=>[p,hash(path.join(dir,p))]))
}
const handoffExists=fs.existsSync("fabrication"),handoff=manifest("fabrication")
const auditHash=hash("reports/fabrication-audit.json")
const exported=spawnSync("python3",["scripts/export-assembly.py"],{encoding:"utf8"})
assert.notEqual(exported.status,0)
assert.match(exported.stderr,/JLCPCB orderable assembly stock is insufficient/)
assert.deepEqual(manifest("fabrication"),handoff)
assert.equal(fs.existsSync("fabrication"),handoffExists)
assert.equal(hash("reports/fabrication-audit.json"),auditHash)
const report={checkedAt:new Date().toISOString(),circuitSha256,results,
  assemblyExportBlocked:true,previousHandoffFilesPreserved:Object.keys(handoff).length,
  previousAuditPreserved:true,thermalProcessStillUnqualified:!read("reports/solder-process-audit.json").approvedForAssembly,
  fabricationReady:false}
fs.writeFileSync(process.env.RELEASE_GATE_REPORT??"reports/round9-release-gates.json",JSON.stringify(report,null,2)+"\n")
console.log(JSON.stringify(report))