# SYSADMIN CHRONICLES — AGENT WORKING RULES > Version 2.0 | Status: Enforced > > Changelog: > v2.0 — Rewritten for Node.js + Svelte era. GDScript/Godot rules removed. > v1.1 — GDScript-specific rules (superseded). > > Read this file FIRST before touching anything else. These rules prevent content > corruption, broken cross-references, and silent design drift. --- ## 0. ALWAYS READ FIRST Before doing any work, read these files in order: 1. `AGENT_RULES.md` (this file) 2. `OPEN_ISSUES.md` — current known issues and decisions in progress 3. `docs/ARCHITECTURE.md` — system design and constraints 4. `docs/QUEST_AUTHORING.md` — content schema and validation rules If you are working on a specific domain, also read: - Content work → `docs/QUEST_AUTHORING.md` + relevant `content/world_flags/world_flags.json` - VM work → `docs/ARCHITECTURE.md` sections 5 and 6 - Save system work → `docs/SAVE_SYSTEM.md` - Server work → `server/src/` — read the relevant service file before editing --- ## 1. WHAT YOU MAY DO WITHOUT ASKING - Add new `.js` or `.svelte` files in `server/src/` or `frontend/src/` following existing conventions - Add new JSON content files in `content/` that pass content validation - Add new shell scripts in `tools/` that do not modify VM state - Edit files you created in the current working session - Run read-only commands: `cat`, `ls`, `grep`, `diff`, `virsh domstate`, probes - Run content validation: `node tools/content/validate-content.js` - Run server tests: `cd server && npm test` - Create new files in `tools/vm/quest-prep/` for new quests ## 2. WHAT YOU MUST ASK BEFORE DOING - Modifying `docs/ARCHITECTURE.md`, `docs/QUEST_AUTHORING.md`, `docs/SAVE_SYSTEM.md`, or `docs/ROADMAP.md` - Modifying `content/world_flags/world_flags.json` - Modifying any existing quest, ticket, incident, or dialogue JSON file - Adding a new Express route or WebSocket event type - Changing any validation rule type name or schema field name - Changing VM profile IDs, snapshot names, or network profile names - Any `virsh` command that modifies state: `start`, `destroy`, `snapshot-create`, `snapshot-revert` - Any `tools/vm/` script that writes to a VM image ## 3. WHAT YOU MUST NEVER DO - Delete any file (use a rename to `.bak` and ask first) - Run `virsh undefine`, `virsh pool-delete`, or `virsh net-destroy` without explicit instruction - Run `tools/vm/snapshot-all.sh --revert-to` without explicit instruction - Modify a VM's baseline snapshot or `baseline.clean` state - Run provisioning scripts (`Q0XX-prep.sh`) against any VM without explicit instruction - Add a world flag reference in any content file without first adding it to `world_flags.json` - Create a solution branch with a `priority` that duplicates an existing branch in the same quest - Set `follow_up_incident` to an incident ID that does not exist as a file - Set `series_id` in a dialogue file without ensuring at least 2 members share that series_id - Modify the save file schema without updating `server/src/services/SaveState.js` and the migration handler - Ignore content validation errors and proceed anyway --- ## 4. CONTENT AUTHORING RULES ### World Flags - Every flag used anywhere must exist in `content/world_flags/world_flags.json` - When you set a flag in a quest or incident, update `set_by` in the registry - When you read a flag in a quest, incident, or dialogue, update `read_by` - Conflicting flags must list each other in `conflicts_with` - A flag with `persists: false` resets at the start of each new shift (not on load) ### Quests - Every quest must have a `clue_fingerprint` with at least one evidence entry - Every quest must declare `required_vms` — list ALL VMs touched, not just the primary - Branch priorities must be unique within a quest — no two branches share a priority number - The highest-priority branch that matches wins — author branches so better fixes have higher priority - Do not author a branch that cannot be distinguished from another branch by validation rules alone ### Tickets - Both `initial_priority` and `current_priority` must be present and equal at authoring time - `current_priority` is the only field the runtime modifies — never change `initial_priority` at runtime ### Incidents - Every incident must declare `blast_radius_quests` (can be empty array, never omit) - Every incident must declare `blast_radius_incidents` (can be empty array, never omit) - `follow_up_incident` in a quest branch must map to an incident file that exists ### Dialogue - If `series_id` is declared, `series_position` must also be declared - A `series_id` must have at least 2 dialogue files sharing it before content passes validation - `trigger: "world_flag:{id}"` — the flag ID must exist in the registry ### File Naming - Quest files: `Q{NNN}-{kebab-case-title}.json` - Ticket files: `T{NNN}.json` - Incident files: `I{NNN}-{kebab-case-title}.json` - Dialogue files: `{character}-Q{NNN}.json` or `{character}-Q{NNN}-{variant}.json` - Do NOT bundle multiple dialogue characters or quests into one file - VM profiles: `{snake_case}.json` - Quest prep scripts: `Q{NNN}-prep.sh` --- ## 5. CODE AUTHORING RULES ### Node.js (server/src/) - All host commands go through `server/src/lib/ssh.js` or `server/src/lib/virsh.js` — never use `child_process` directly in service files - All VM lifecycle actions go through `VMManager.js` — never call libvirt directly from quest or validation logic - Never hardcode VM domain names — use constants from `ContentLoader` or the VM profile JSON - All world flag reads and writes go through `QuestEngine.js` — never mutate flags directly - Trust changes go through `TrustSystem.js` — never modify trust score directly - Services coordinate via `eventBus.js` (Node EventEmitter) — no service may `require()` another service and call its internals directly; emit events instead - All save-state writes go through `SaveState.js` ### Svelte (frontend/src/) - All API calls go through `frontend/src/lib/api.js` — no raw `fetch()` in components - WebSocket events are received in `App.svelte` and distributed to panels via Svelte stores or props — panels do not open their own WebSocket connections - No game logic in Svelte components — components render state and dispatch user actions only ### Validation Rules - Every new rule type must be added to `server/src/services/ValidationEngine.js` and the QUEST_AUTHORING.md rule reference table - Rules must only observe state — they must never modify VM state ### Shell Scripts - All scripts in `tools/vm/` must print a dry-run summary before modifying anything - All scripts must be idempotent — running them twice must produce the same result - Scripts that require root must check for permissions and exit clearly if absent - Use `sc-` prefix for all libvirt resources created by the game --- ## 6. VM SAFETY RULES - Never operate on a VM domain that does not start with `sc-` - Never revert a snapshot during an active quest without explicit player/developer instruction - The workstation VM (`sc-workstation`) must stay live during all gameplay — never suspend it mid-session - If a probe or validation script fails, log the failure and return a degraded-state result — never crash the server - All SSH connections from the host to guests use key-based auth only — no passwords in scripts --- ## 7. HOW TO HANDLE AMBIGUITY If you are unsure whether something is correct: 1. Check `OPEN_ISSUES.md` — the answer may already be there 2. Check `docs/QUEST_AUTHORING.md` for schema rules 3. Check `content/world_flags/world_flags.json` for flag semantics 4. If still unsure, **stop and ask** rather than making an assumption Do not proceed with a best-guess implementation of something that is in `OPEN_ISSUES.md` as unresolved. Wait for a decision. --- ## 8. AFTER MAKING CHANGES After any content change: - Run `node tools/content/validate-content.js` and confirm zero errors - If you added a world flag, confirm it appears in `world_flags.json` with correct `set_by` and `read_by` - If you added a quest, confirm its prep script exists or is noted as pending in `OPEN_ISSUES.md` After any server code change: - Run `cd server && npm test` and confirm no regressions - If you added a new validation rule type, add it to `docs/QUEST_AUTHORING.md` After any architectural change (new route, new VM, new service, new WebSocket event): - Update `docs/PROJECT_MAP.md` — boot flow, service graph, VM identity table, or known gaps as applicable --- ## 9. DO NOT SILENTLY FIX DESIGN ISSUES If you discover a design inconsistency (e.g., two quests that conflict, a flag used incorrectly, a branch that cannot be validated), do NOT silently patch it. Instead: 1. Add it to `OPEN_ISSUES.md` with a clear description 2. Flag it in your response to the developer 3. Wait for a decision before changing any content The exception is purely mechanical errors (typos, missing commas, wrong field names) where the intent is unambiguous — those can be fixed directly.