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/write-round9-status.mjs
import fs from "node:fs"
import crypto from "node:crypto"
import assert from "node:assert/strict"
const read=p=>JSON.parse(fs.readFileSync(p,"utf8"))
const hash=p=>crypto.createHash("sha256").update(fs.readFileSync(p)).digest("hex")
const file="dist/index/circuit.json",circuit=read(file),sha=hash(file)
const baseline="../../checkpoints/nema17-round8-validated-local-20261020-ii8Wrw/restore-verified"
const regression=read("reports/round9-regression.json"),stock=read("reports/jlcpcb-stock-audit.json")
const solder=read("reports/solder-process-audit.json"),continuity=read("reports/connectivity-audit.json")
const copper=read("reports/coil-all-copper-preflight-meta.json"),drill=read("reports/drill-clearance-regression.json")
const dfm=read("reports/additional-dfm-review.json"),bom=read("reports/bom-validation.json")
const gates=read("reports/round9-release-gates.json")
for(const r of [regression,stock,solder,continuity,copper,drill,dfm,bom,gates])assert.equal(r.circuitSha256,sha)
assert.deepEqual(solder.ordinaryPadDrillIntersections,[])
assert.equal(solder.thermalPadDrillIntersections.length,16)
assert.equal(continuity.sourceFailures,0);assert.equal(continuity.disconnectedTerminalIslands,0)
assert.equal(copper.failureCount,0);assert.equal(copper.physicalCopperSha256,hash("routing/physical-copper.json"))
assert.equal(drill.currentFindings,0);assert.equal(drill.regressionCount,0)
assert.deepEqual(dfm.findings,[]);assert.deepEqual(bom.findings,[])
assert.deepEqual(read("reports/round5-legend-audit.json").findings,[])
const log=f=>fs.readFileSync(`reports/round9-${f}.log`,"utf8")
assert.match(log("build"),/Circuits\s+1 passed/)
assert.match(log("shorts"),/No shorts detected/)
assert.match(log("board-tests"),/6 pass[\s\S]*0 fail/)
assert.match(log("module-tests"),/32 pass[\s\S]*0 fail/)
assert.match(log("verify"),/all JLCPCB parts cover board quantity/)
assert.match(log("motion-tests"),/PASS: signed coil conversion/)
assert.match(log("host-tests"),/Ran 6 tests[\s\S]*OK/)
const warnings=circuit.filter(e=>e.type.endsWith("_warning"))
const old=read(`${baseline}/dist/index/circuit.json`)
const oldWarnings=old.filter(e=>e.type.endsWith("_warning"))
const warningKey=e=>`${e.type}:${e.source_trace_id??""}:${(e.message??"").replaceAll("0.12000000000000001","0.12")}`
const prior=new Set(oldWarnings.map(warningKey))
const added=warnings.filter(e=>!prior.has(warningKey(e)))
assert.equal(added.length,1);assert.equal(added[0].source_trace_id,"source_trace_135")
assert.equal(warnings.length,oldWarnings.length+1)
const widths={}
for(const t of circuit.filter(e=>e.type==="pcb_trace"&&e.source_trace_id==="source_trace_305")){
for(let i=1;i<t.route.length;i++){
const a=t.route[i-1],b=t.route[i]
if(a.route_type!=="wire"||b.route_type!=="wire"||a.layer!==b.layer)continue
assert.ok(["top","bottom"].includes(a.layer))
const w=Number(Math.min(a.width,b.width).toFixed(4))
widths[w]=(widths[w]??0)+Math.hypot(a.x-b.x,a.y-b.y)
}
}
assert.ok(widths[.5]>7&&widths[.5]<9)
const resistanceOhm=1.724e-8*(widths[.5]*1e-3)/(.5e-3*35e-6)
const issues=stock.parts.filter(p=>p.status!=="in-stock")
assert.deepEqual(issues.map(p=>p.code).sort(),["C32843","C85202"])
const evidence=["reports/round9-regression.json","reports/solder-process-audit.json","reports/connectivity-audit.json",
"reports/coil-all-copper-preflight-meta.json","reports/coil-all-copper-preflight.json","reports/drill-clearance-regression.json",
"reports/additional-dfm-review.json","reports/jlcpcb-stock-audit.json","reports/bom-validation.json",
"reports/module-test-regression.json","reports/round9-release-gates.json","reports/round9-pin-glyph-bounds.json",
"reports/round5-legend-audit.json","reports/round9-pcb-top.png","reports/round9-pcb-bottom.png",
...["build","continuity","copper","solder","shorts","drill","dfm","kelvin","mechanical","legend","glyphs",
"check","style","typecheck","board-tests","module-tests","module-regression","motion-tests","host-tests",
"stock","bom","verify","gate-tests"].map(f=>`reports/round9-${f}.log`)]
const report={checkedAt:new Date().toISOString(),circuitSha256:sha,replaySha256:hash("routing/complete-routes.json"),
ordinaryConflictsAllResolved:true,allOtherIssuesResolved:false,fabricationReady:false,localChangesNotPushed:true,
baselineCircuitSha256:hash(`${baseline}/dist/index/circuit.json`),
resolved:read(`${baseline}/reports/solder-process-audit.json`).ordinaryPadDrillIntersections,
method:"Seven real component placements and explicit copper reroutes. PD-enable and driver-shunt escapes moved out of ordinary solder lands. No thermal drill deleted, land shrunk, outline enlarged or clearance relaxed.",
movedComponents:regression.movedComponents,
invariants:{outlineMm:42.3,mounts:4,mountPatternMm:31,layers:4,thicknessMm:1.6,
actualVias:regression.throughVias,viaDrillMm:.3,viaPadMm:.45,allViasFullStack:true,
electricalNetlistAndValuesUnchanged:true,footprintAndLandSizesUnchanged:true,firmwareFilesUnchanged:regression.firmwareFilesUnchanged,
allOriginalSourceTraceConstraintsRetained:true,allUnlistedComponentsAndConnectorsUnmoved:true},
powerCopperChange:{oldMotorAreaCrossbarWidthMm:.8,replacementSectionWidthMm:.5,
minimumMotorShuntReturnWidthMm:.3,allOnOuterLayers:true,vmSourceRouteLengthByWidthMm:widths,
dcEstimate:{assumedCopperUm:35,assumedCopperTemperatureC:20,assumedCurrentA:.8,
halfMmSectionsTotalResistanceOhm:resistanceOhm,dropV:resistanceOhm*.8,lossW:resistanceOhm*.8*.8,
scope:"DC estimate of 0.50 mm sections only, not total supply impedance, RMS/thermal/transient certification or a substitute for bench measurements."}},
checks:{nativeErrors:0,nativeWarnings:warnings.length,baselineNativeWarnings:oldWarnings.length,addedNativeWarnings:added,
ordinaryPadDrillIntersections:0,thermalIntersectionRecords:16,thermalStitchesRemoved:0,
allLayerGerberShorts:"pass",emittedOnlyContinuity:"pass; all terminals, no pours needed",independentCopper:"pass",
independentDrill:"pass, zero findings/regressions",mechanical:"pass",printedLegend:"pass with unchanged font/stroke/clearances; numeric ink-outline bounds measured",
kelvin:"all four phase/polarity paths pass, joining only at the corresponding shunt land",
schematic:"unchanged records; CLI placement check passes. No new cloud AI style-analysis or 3D inspection claimed.",
typecheck:"pass",bomCatalogValues:"199 populated parts checked; no findings",
moduleTests:{passed:32,failed:0,originalTestFilesUnchanged:true},boardTests:{passed:6,failed:0},firmwareAndHostTests:"pass; sources unchanged",
fullVerification:{passed:false,reason:"live JLCPCB orderable stock shortage",assemblyExportBlocked:true},negativeReleaseGateTests:"pass"},
stock:{checkedAt:stock.checkedAt,populated:stock.populatedComponentCount,uniqueCodes:stock.uniquePartCount,boardQuantity:stock.boardQuantity,
reserved:false,shortages:issues.map(p=>({code:p.code,designators:p.designators,mpn:p.manufacturerPartNumber,
displayed:p.displayedStock,orderable:p.orderableStock,required:p.requiredForBatch,url:p.url})),
caveat:"Displayed stock is not proven orderable assembly inventory. No depleted part waived or silently substituted."},
remaining:{thermalSolderProcess:"16 intentional thermal-pad/drill records remain; double-sided stencil/opposite-face and via treatment must be qualified. Tenting is not filled/capped approval.",
inventory:"W5500 C32843 and BSS84-7-F C85202 fail the fresh orderable-stock gate; purchasing/preorder or a verified compatible redesign is required before assembly release.",
warnings:"153 native warnings, versus 152; the added Ethernet rail-path warning requests 0.25 mm and observes 0.15 mm. Existing width warnings and this warning are disclosed, not waived as minor.",
signalIntegrity:"Controlled stackup and USB/Ethernet return-path qualification remain.",
actualMotorInterface:"Actual rear endbell, fastening method and bolt length are unconfirmed; a standard NEMA17 front pattern does not establish rear mounting.",
bench:"Flashing, hardware watchdog fault injection, current calibration, rail/load/thermal/transient and motor/harness tests remain.",
previousVerificationFile:"verification.json belongs to the previous circuit; the current full verification fails closed on stock. This hash-bound round9 status is the current evidence summary.",
publication:"Not pushed; no registry/default-version change performed."},
evidence:Object.fromEntries(evidence.map(p=>[p,hash(p)]))}
fs.writeFileSync("reports/round9-fix-status.json",JSON.stringify(report,null,2)+"\n")
console.log(JSON.stringify({circuitSha256:sha,ordinaryConflicts:0,nativeErrors:0,nativeWarnings:warnings.length,
modules:report.checks.moduleTests,stockShortages:issues.map(p=>p.code),fabricationReady:false,localChangesNotPushed:true}))