Files
personaEngine2/specs/001-persona-engine/contracts/cli-edit-persona-engine-config.md
T
2026-08-21 01:18:19 -04:00

114 lines
5.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Contract: `Edit-PersonaEngineConfig.ps1`
Configuration validation, interactive editing, synthetic rule testing, and pipeline enforcement
(FR-023 FR-026).
## Signature
```powershell
[CmdletBinding(SupportsShouldProcess = $true)]
param(
[Parameter(Mandatory)][string] $ConfigPath,
[Parameter()][switch] $ValidateOnly,
[Parameter()][switch] $NonInteractive,
[Parameter()][string] $SchemaPath,
[Parameter()][string] $OutputPath,
[Parameter()][switch] $TreatWarningsAsErrors,
[Parameter()][string] $TestDataPath
)
```
## Parameter contract
| Parameter | Behaviour |
| --- | --- |
| `-ConfigPath` | Required. Configuration to validate or edit. |
| `-ValidateOnly` | Validate and report; never enter the editor. |
| `-NonInteractive` | Pipeline mode. **MUST NOT prompt and MUST NOT hang** (SC-010). Returns an exit code. |
| `-SchemaPath` | Override the shipped schema. |
| `-OutputPath` | Save-As target; leaves the input file untouched. |
| `-TreatWarningsAsErrors` | Escalates `Warning` findings to blocking (VR-005). |
| `-TestDataPath` | Synthetic sample users for offline rule testing (FR-025). No tenant connectivity. |
## Validation layers (VR-001, ordered, fail-fast between layers)
| Layer | Mechanism | Example findings |
| --- | --- | --- |
| 1. Syntax | `ConvertFrom-Json` | Malformed JSON |
| 2. Schema | `Test-Json -SchemaFile` (draft-07, OTD-005) | Missing required field, wrong type, bad enum |
| 3. Semantic | PowerShell checks | Every condition in VR-002 |
| 4. Safety | PowerShell checks | Every condition in VR-003 |
A layer that produces `Error` findings stops the sequence — running semantic checks over a
structurally invalid document yields noise, not signal.
### Layer 2 error-handling requirement
`Test-Json` reports schema failure by writing errors rather than returning `$false` in several
PowerShell versions. The wrapper MUST invoke it with `-ErrorAction SilentlyContinue -ErrorVariable`
and convert collected errors into `ValidationFinding` objects, so layer 2 emits the same structured
shape as every other layer (VR-004).
## Finding contract
Every finding carries `Severity`, `Code`, `Location` (JSON path or rule ID), `Description`,
`SuggestedResolution`, and `Layer`. Finding codes are stable and namespaced by layer:
```text
PE-SYN-nnn syntax
PE-SCH-nnn schema
PE-SEM-nnn semantic (one code per VR-002 condition)
PE-SAF-nnn safety (one code per VR-003 condition)
```
Stability matters: pipelines and runbooks will match on these codes.
## Exit codes
| Code | Condition |
| --- | --- |
| `0` | Valid; no blocking findings |
| `1` | One or more `Error` findings |
| `2` | `Warning` findings present with `-TreatWarningsAsErrors` |
| `3` | Configuration file not found or unreadable |
| `4` | Schema file not found or itself invalid |
## Interactive editor commands (FR-023, FR-027 FR-030)
The interactive loop (entered when neither `-ValidateOnly` nor `-NonInteractive` is set) supports:
| Command | Behaviour |
| --- | --- |
| List rules | Show every rule's priority, ID, persona, and enabled state. |
| Toggle a rule | Flip `enabled` on an existing rule. |
| Change a priority | Set a new numeric priority on an existing rule. |
| **Add a rule** | Prompt for every RE-001 field (`id`, `name`, `description`, `priority`, `persona`, `enabled`, and optional fields) and for the condition tree — nested `all`/`any` groups and, per leaf condition, the property/membership source, operator, and comparison value. Reject on the spot if the `id` or `priority` collides with an existing rule (FR-027). |
| **Edit a rule** | Select an existing rule by `id`; change any top-level field and/or the condition tree — add, edit, remove, or renest conditions and groups within `MaxConditionDepth` (FR-028). |
| **Delete a rule** | Select an existing rule by `id`; show its `id`, `name`, and `priority` and require explicit confirmation before removing it (FR-029). |
| Re-validate | Run all four validation layers against the in-memory document, including any unsaved add/edit/delete, and print findings without saving. |
| Run rule test | Evaluate the in-memory document (including unsaved structural edits) against `-TestDataPath` fixtures. |
| Save | Re-validate, then persist per the save contract below. |
| Quit | Warn if there are unsaved changes (including structural edits) before discarding them. |
All structural edits (add/edit/delete) are applied to the in-memory document only. They are never
written to `-ConfigPath` (or `-OutputPath`) until a `Save` re-validates the full document and that
validation passes — the same rule that governs field-level edits (FR-030). A depth violation
introduced by an add or edit is reported immediately using the same finding the runtime validator
would produce, rather than deferred to the next save or re-validate.
## Save contract (FR-026)
1. Re-validate the edited document in full.
2. Block the save on any `Error` finding.
3. Write a timestamped backup — or require `-OutputPath` — before replacing an existing file.
4. Overwriting the only valid configuration without a backup is a safety finding (VR-003), not
merely a warning.
## Invariants (test-asserted)
| Invariant | Assertion |
| --- | --- |
| Non-interactive never prompts | Runs to completion with stdin closed; no prompt, no hang (SC-010) |
| Every VR-002/VR-003 condition detected | One test per condition, each asserting code, severity, and location (SC-009) |
| Offline | Full validation and synthetic rule testing complete with no network access (SC-008) |