# 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.
