Developer tools local runner — early operational release

Requirements: Node.js 20 or later on Mac, Windows or Linux. Run only against evidence you own or are authorised to inspect. No account or subscription is required for this early local runner.

1. Unzip the complete folder. Keep the runtime directory intact, including collect.mjs. For collector refresh, keep the collectors directory beside runtime.
2. Prepare input JSON using a tool's input template or collectors. Keep inputs outside the output directory. Replace illustrative data before using real results.
3. Save a configuration JSON beside this README, for example:

{
  "authorised": true,
  "intervalSeconds": 60,
  "retention": 20,
  "output": "./monitor-results",
  "checks": [
    {"id": "data-rules", "product": "integrity", "input": "./data.json", "maximumAgeSeconds": 3600}
  ]
}

Use these product keys: changetrace, dependencies, config, integrity, release, capsule, store. You can configure up to 20 uniquely named checks. Paths are relative to the configuration file.

4. Run one check:
   node monitor.mjs configuration.json --once

5. Or repeat until stopped:
   node monitor.mjs configuration.json --watch

Stop with Ctrl+C. The process must remain running; it is not a background cloud service and does not run while your computer is asleep. It re-reads the specified input files. An explicitly configured GitHub collector fetches fresh ChangeTrace evidence. An explicitly configured SQLite collector reads selected local tables and columns. Other tools need refreshed collector outputs supplied separately; OSV requests require the explicit queryOsv permission described below. maximumAgeSeconds checks the file modification time, not the truth or collection time of its contents.

Output: monitor-results/<check-id>/latest.json records success or error, and the generated report. Changed results also create bounded history files; retention defaults to 20 per check and can be 1–100. Terminal notices are printed when results change. No email, chat message or external notification is sent. An error replaces the prior success in latest.json, so stale success is not presented as a current check. The report object inside latest.json uses the browser report format; this wrapper is not an evidence input.

Exit codes: 0 = one-shot analyses completed; 2 = at least one analysis failed; 1 = configuration or runner failure. Code 0 does not mean zero findings or a healthy target. Inspect status, example flag, observations and report limitations.

Inputs stay local. Report history may contain sensitive names, URLs and diagnostic logs; protect the output directory and review before sharing. Only choose a dedicated output directory. Existing reports are replaced and history older than the chosen retention is removed inside it. Never use your evidence directory as output.

A .monitor.lock prevents concurrent writers. After a force quit or power loss, confirm no monitor is using this folder before removing the stale lock. Corrupt previous state stops the runner for review. Changes to configuration require a restart. Failed collectors must not silently preserve an old input file as current; use maximumAgeSeconds and check collector exit status.

GitHub evidence refresh (ChangeTrace)
-----------------------------------
A check may now include this collector object:
  "collector": {
    "type": "github",
    "repository": "OWNER/REPO",
    "service": "api",
    "environment": "production",
    "incidentAt": "2026-10-15T09:30:00+11:00",
    "includeDeployments": true
  }
The repository must be authorised under your existing gh login. Python 3 and gh
must be on PATH. The input path becomes the collector output; its parent must
already exist. The monitor refreshes before each analysis in --once and --watch.
It runs a fixed collector without a shell, bounds each collection to 120 seconds,
and atomically replaces evidence only after collection succeeds. Private evidence
files are created with owner-only permissions on POSIX systems. A failed refresh
records an error; old evidence is preserved but is not presented as fresh success.
Configured collectors require intervalSeconds of at least 60. Checks run sequentially, then wait intervalSeconds; this is not a fixed-rate SLA.
GitHub, scoped SQLite, npm and configuration refresh are supported. Other tools still need externally refreshed
input. No external notification delivery or hosted connector is implemented.

SQLite evidence refresh (Data Integrity Sentinel)
------------------------------------------------
An integrity check can include:
  "collector": {
    "type": "sqlite",
    "database": "./data.sqlite",
    "spec": "./rules.json"
  }
Paths resolve relative to the configuration file. Python 3 must be on PATH.
The specification explicitly selects tables, columns and integrity rules; see
collectors/README.txt. Only use data you own or are authorised to inspect.
The database is opened read-only. The input path receives the scoped snapshot;
keep database, specification and evidence outside the report output directory.
Do not point input at the database or specification. The same timeout, atomic
replacement, private-file permissions and failure handling as GitHub apply.
Snapshots and reports can contain selected customer data; protect these files.

npm evidence refresh (Dependency Guardian)
-----------------------------------------
A dependencies check can include:
  "collector": {
    "type": "npm",
    "lockfile": "./package-lock.json",
    "queryOsv": true
  }
Setting queryOsv:true authorises sending package names and exact versions to the
public OSV advisory service. Source code, private registry URLs and credentials
are not sent. Set false for an offline inventory with incomplete advisory coverage.
This choice is required. OSV checks require intervalSeconds of at least 3600;
checks run sequentially and may take up to 120 seconds before recording a timeout.
Node.js must be available. Lockfile v2/v3 only; unknown/local versions are unresolved.
The lockfile must be outside the report directory and different from input.
Each successful collection updates lookup times; history records fresh coverage
as well as changed advisories. The bounded retention setting still applies.
Network failures record errors and never reuse stale evidence as a clean result.
Pagination is bounded; unfinished lookups remain explicitly incomplete.

Configuration evidence refresh (ConfigGuard)
-------------------------------------------
Create a baseline once from an authorised local JSON configuration map:
  python3 ../collectors/config_snapshot.py --input ./configuration.json --key ./fingerprint.key --create-key --environment staging --output ./baseline.json
On Windows use python instead of python3. Run this from the runtime directory or
adjust paths. --create-key refuses an existing key. Omit it to reuse your key.
Keep the key private; protect configuration files with your normal OS permissions.
Never put passwords into configuration entry names: names appear in reports.

A config check in your monitor configuration can include:
  "collector": {
    "type": "config",
    "configuration": "./configuration.json",
    "keyFile": "./fingerprint.key",
    "baseline": "./baseline.json",
    "environment": "staging"
  }
As with other checks, set product to config and input to a separate evidence.json.
Collector paths resolve relative to the monitor configuration file. The baseline
must be a fingerprint snapshot for the same environment and key. Each cycle reads
the current JSON and compares fingerprints to this fixed baseline. It never
changes the configuration, baseline or key and never sends them over the network.
Only names and HMAC fingerprints enter evidence; fingerprints are excluded from
analysis reports. Key rotation requires an explicitly regenerated baseline.
Malformed/oversized files, duplicate baseline names, wrong keys or environments
produce errors, preserving previous evidence without presenting it as current.
Use a new baseline filename when intentionally accepting configuration changes;
review it and update monitor configuration, then restart the monitor. Baselines
are never silently advanced. Keep all three sources outside the reports folder.

Release Guardian: refresh local request telemetry
------------------------------------------------
Export authorised observations to JSONL (one JSON object per line). Each row
needs id, at (ISO timestamp with timezone), environment, release, metric and
failed (true/false). Use a stable unique observation id; repeat deliveries are
counted once and conflicting duplicates fail collection. Additional fields are
not exported. This collector never requests or transmits data over a network.

Example row:
{"id":"request-1","at":"2026-10-16T12:00:00Z","environment":"production","release":"v2","metric":"checkout","failed":false}

Create windows.json:
{"environment":"production","metric":"checkout","baseline":{"release":"v1","start":"2026-10-15T00:00:00Z","end":"2026-10-16T00:00:00Z"},"current":{"release":"v2","start":"2026-10-16T00:00:00Z","end":"2026-10-17T00:00:00Z"}}

A monitor check can use:
{"id":"release","product":"release","input":"release-evidence.json","collector":{"type":"release-jsonl","observations":"events.jsonl","spec":"windows.json"}}

Use authorised:true and the usual monitor output/interval settings. Paths are
relative to your monitor configuration. Run once first and review latest.json.
The source JSONL is limited to 20 MB and 100,000 rows; no truncation is silent.
Window start is included and end excluded. Missing windows remain unknown.
Re-running collects late-arriving observations within these fixed windows.
Collection completeness, representative traffic and causal attribution still
need review. This is local aggregation, not a hosted telemetry connector.
