working-on-factorio — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited working-on-factorio (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
Factorio uses a hybrid mod + daemon architecture — unique among Savecraft plugins. A Lua mod writes JSON to script-output/savecraft/, the daemon watches via fsnotify, and a thin WASM parser converts to ndjson. Design doc: plugins/factorio/README.md.
plugins/factorio/
├── mod/ # Factorio Lua mod (control.lua, info.json)
├── parser/ # WASM pass-through parser (JSON → ndjson)
├── reference/ # WASM reference modules (recipe_lookup, ratio_calculator)
│ ├── data/ # Generated Go struct literals (*_gen.go)
│ └── views/ # Svelte reference views (ratio-calculator.svelte)
├── tools/
│ ├── datagen/ # Parses data-raw-dump.json → generated Go files
│ └── spritesheet/ # Packs icon PNGs into sprite sheet + manifest
├── sprites/ # Generated sprite sheets (items.png, fluids.png + JSON manifests)
├── plugin.toml # Plugin metadata, sources = ["wasm", "mod"]
└── Justfilecd plugins/factorio
just test # Parser + reference module tests (32 tests)
just build # Build parser.wasm + reference.wasm
just datagen # Regenerate from data-raw-dump.json
just spritesheet # Regenerate sprite sheets from .reference/ PNGsFull suite: just test-go (all Go) + just test-worker (all Worker) + just build-views (view compilation).
View changes require `just build-views` + committing `views.gen.ts`. See working-on-views skill for details. CI does not rebuild views — forgetting this ships stale HTML.
Never guess which recipe to use. When multiple non-recycling recipes produce the same item (e.g., solid-fuel from 3 oil sources), resolveRecipe() returns an error listing the options. The AI uses recipe_lookup (product query) to find options, picks contextually, and passes the explicit recipe name via the recipe or recipe_overrides parameters.
recipe_lookup and tech_tree_navigator return data for the LLM to reason over. No player-facing visualization — the AI narrates results. Views exist only for modules whose output the player needs to SEE (ratio_calculator, oil_balancer, etc.).
FlowChart lives in views/src/components/charts/ (shared, game-agnostic Sankey-style flow visualization). Factorio-specific components (ProductionChain, MachineNode, factorio-colors.ts) live in plugins/factorio/components/. FactorioIcon is in views/src/components/factorio/.
.reference/factorio-data-raw-dump.json # factorio --dump-data (27MB, all prototypes)
.reference/factorio-sprites/{item,fluid,...}/ # factorio --dump-icon-sprites (64x64 PNGs)
.reference/factorio-locale/*-locale.json # factorio --dump-prototype-locale (display names)
.reference/factorio-saves/ # Test save files# SSH to Steam Deck ([email protected], password in memory)
# WARNING: Factorio CLI commands may steal focus from active games on the Deck
nix-shell -p sshpass --run 'sshpass -p "..." ssh [email protected] \
"~/.steam/steam/steamapps/common/Factorio/bin/x64/factorio --dump-data"'
# Then SCP from ~/.factorio/script-output/.reference/factorio-data-raw-dump.json
→ go run ./plugins/factorio/tools/datagen/
→ plugins/factorio/reference/data/*_gen.go
recipes_gen.go (659 recipes)
technologies_gen.go (275 techs)
machines_gen.go (17 crafting machines)
modules_gen.go (12 modules)
logistics_gen.go (belts, inserters, beacons)
fluids_gen.go (33 fluids)
→ compiled into reference.wasm (GOOS=wasip1 GOARCH=wasm)Factorio data quirk: Empty collections are {} (object) not [] (array). The datagen tool handles this with parseStringArray().
.reference/factorio-sprites/item/*.png (340 icons, 64x64)
→ go run ./plugins/factorio/tools/spritesheet/
→ plugins/factorio/sprites/items.png (2048x704, 2.3MB)
→ plugins/factorio/sprites/items.json (manifest: name → {x,y,w,h,label})Labels come from .reference/factorio-locale/item-locale.json.
| 1.x | 2.0 |
|---|---|
game.write_file | helpers.write_file |
game.table_to_json | helpers.table_to_json |
game.item_prototypes | prototypes.item |
global | storage |
force.evolution_factor | force.get_evolution_factor(surface) |
mod/info.json — mod metadata, factorio_version: "2.0" (two-part only)mod/control.lua — script.on_nth_tick() hooks: lightweight stats every 300 ticks (5s), heavy entity scans every 1800 ticks (30s)script-output/savecraft/state.jsonGo WASM with baked-in data (RimWorld pattern, NOT native TypeScript like MTGA). Entry point: reference/main.go with query routing.
effective_speed = machine.CraftingSpeed × (1 + module_speed + beacon_speed)
beacon_speed = Σ(module_effect × dist_effectivity / √n) across all beacons
output_per_craft = result_amount × (1 + productivity_bonus)
items_per_sec = (effective_speed / craft_time) × output_per_craftProductivity does NOT increase ingredient consumption — only gives free bonus output. This is validated by TestValidation_ProductivityModules_AM3.
plugins/factorio/reference/main.go switch statementschema() in main.go[reference.modules.*] in plugin.tomlplugins/factorio/reference/views/views/src/attributions.ts has a wube entry for Factorio content. Plugin.toml declares [attribution] sources = ["wube"].
~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.