Add elapsed run time, per-account results CSV, and a default config path

Summaries now show elapsed wall-clock time since the run started, and every
summary (interim and final) overwrites a results.csv (Object ID, UPN,
persona/status) next to the audit log, so an operator has a plain export
without parsing NDJSON. ConfigPath also now defaults to
./config/persona-engine.json instead of requiring -ConfigPath every run.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-24 22:10:24 -04:00
parent 8c8fd47f74
commit 5f125c34f2
14 changed files with 154 additions and 13 deletions
+1
View File
@@ -57,6 +57,7 @@ property-only rules.
| --- | --- | --- | --- |
| `destination` | no | `both` | `file`, `stream`, `both`, or `none`. `stream` writes records to the PowerShell Information stream. |
| `path` | no | `<current-directory>/logs/persona-engine-audit.ndjson` | NDJSON output file. One record per line. |
| `resultsFileName` | no | `results.csv` | Per-account results CSV, written next to `path`'s directory. Lists `AccountObjectId`, `UserPrincipalName`, `PersonaStatus` for every account processed so far. Overwritten on every summary, interim and final. |
| `traceConditionValues` | no | `false` | Writes evaluated attribute values into audit records. |
| `acknowledgeConditionTracing` | no | `false` | **Required whenever `traceConditionValues` is true** (VR-003). |
+13
View File
@@ -38,6 +38,19 @@ warning, **once** per run, and processing continues.
Once, not once per user: a run over five thousand accounts with a locked log file should warn once,
or the warning that matters is buried in the noise it generates.
## Results CSV
Alongside the NDJSON audit log, every summary — interim and final — (re)writes a plain CSV listing
every account processed so far: `AccountObjectId`, `UserPrincipalName`, `PersonaStatus` (the assigned
persona for `Matched` accounts, otherwise `Unclassified` or `EvaluationError`). It is overwritten in
full each time, not appended, so it always reflects the whole run to that point rather than only the
accounts since the last summary.
It is written next to the audit log — same directory as `logging.path` — under `logging.resultsFileName`
(default `results.csv`). Export failure never ends a run, for the same reason a sink failure doesn't:
a locked file or full disk is an operational problem, not a reason to abandon a classification run
mid-population.
## Record types
| Type | When | Carries |
+5 -1
View File
@@ -44,7 +44,11 @@ the header line and `PE-SAF-001`.
A summary appears every `summaryInterval` accounts and once at the end, listing **every** rule
including disabled and zero-match ones. A rule that never fired and a rule that is not in the
configuration look identical if zero-match rules are omitted, and that distinction is usually what
you are looking for.
you are looking for. Its header shows elapsed wall-clock time since the run started.
Each summary also (re)writes `logging.resultsFileName` (default `results.csv`, next to the audit log)
with one row per account processed so far — Object ID, UPN, and assigned persona/status — for an
operator who wants the current population breakdown without parsing NDJSON.
## Exit codes