Skip to content

Commit 6145f5f

Browse files
SahirVhoraclaude
andcommitted
docs: update README for Mode 2 simulation and auto-remediation
Mode 2 is now shipped (not Coming Soon). Document simulator.py API, supported change types (reparent/field_change), remediation.py API, per-check remediation table, confidence levels, and updated test coverage table. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 08f32db commit 6145f5f

1 file changed

Lines changed: 86 additions & 7 deletions

File tree

README.md

Lines changed: 86 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,11 @@ sf-position-integrity-checker/
2121
├── reporters.py # Output writers - HTML, Excel, CSV, run_manifest.json
2222
├── database.py # SQLite helpers - schema, upserts, audit views
2323
├── config.py # Credential resolution - .env, keyring, interactive prompt
24+
├── simulator.py # Mode 2 simulation engine - pre-change impact analysis
25+
├── remediation.py # Auto-remediation payload builder and dry-run writer
2426
├── test_schema.py # Offline test suite - no SF credentials needed
27+
├── test_simulator.py # Offline tests for simulator (no OData calls)
28+
├── test_remediation.py # Offline tests for remediation (no OData calls)
2529
├── auth/
2630
│ ├── basic.py # Basic Auth request handler
2731
│ └── oauth2.py # OAuth2 SAML Bearer token handler (signed assertion + auto-refresh)
@@ -64,13 +68,13 @@ Run this after any major foundation change, as part of a periodic data health ch
6468

6569
---
6670

67-
### 🔄 Mode 2 - Pre-Change Impact Analysis *(Coming Soon)*
71+
### 🔄 Mode 2 - Pre-Change Impact Analysis
6872

6973
> *"If I change this foundation object, how many positions will break - and which ones?"*
7074
71-
Before making a foundation change, know exactly what downstream impact it will have. The tool will let you simulate a proposed change and surface every affected Position and Job Information record - giving your team a remediation list before the change is applied, not after.
75+
Before making a foundation change, know exactly what downstream impact it will have. Simulate a proposed change against the locally cached extract and get a full impact report - newly failing positions, newly passing positions, and a per-check breakdown - before anything is touched in the live tenant.
7276

73-
**Real-world scenarios this will handle:**
77+
**Real-world scenarios:**
7478

7579
| Foundation Change | Impact Question |
7680
|---|---|
@@ -80,7 +84,39 @@ Before making a foundation change, know exactly what downstream impact it will h
8084
| Job Code Career Path updated | How many positions have a mismatched Career Path after the change? |
8185
| Division relinked to a different Business Unit | Which positions will fail the Division → BU alignment check? |
8286

83-
This replaces what is currently a manual process - running multiple SF reports, cross-referencing in Excel, and hoping nothing was missed - with a single command that produces a structured impact report.
87+
**Usage (Python API):**
88+
89+
```python
90+
from simulator import simulate_change
91+
92+
result = simulate_change(
93+
change={
94+
"type": "reparent", # or "field_change"
95+
"entity_type": "departments", # departments, sub_departments, job_codes,
96+
# divisions, business_units, cost_centers,
97+
# companies, locations
98+
"code": "DEPT-123",
99+
"field": "cust_Division",
100+
"old_value": "DIV-A",
101+
"new_value": "DIV-B",
102+
},
103+
country="GBR",
104+
)
105+
106+
print(result["net_impact"]) # positive = more failures
107+
print(result["newly_failing"]) # list of newly broken positions
108+
print(result["newly_passing"]) # list of positions this change fixes
109+
print(result["check_breakdown"]) # {"CHK-02": 14, "CHK-03": 3}
110+
```
111+
112+
Supported change types:
113+
114+
| type | What it does |
115+
|------|-------------|
116+
| `reparent` | Updates a navigation link on a foundation record (e.g. move a Department to a different Division). Affects CHK-01 to CHK-05. |
117+
| `field_change` | Updates a scalar field on a foundation record (e.g. change a Job Code's grade). Affects CHK-06 to CHK-09. |
118+
119+
Zero OData calls are made. The simulation runs entirely against the local SQLite cache.
84120

85121
---
86122

@@ -100,6 +136,44 @@ This replaces what is currently a manual process - running multiple SF reports,
100136

101137
Rules are defined in `config/rules.yaml`. Each rule has an `enabled` flag and a `visible` flag - see [Customising rules](#customising-rules) for details.
102138

139+
### Auto-Remediation Payload Generation
140+
141+
For issues on CHK-01 to CHK-09, the tool can derive the correct value from the locally cached foundation data and generate an OData PATCH payload ready to apply back to the tenant.
142+
143+
```python
144+
from remediation import build_remediation_pack, apply_remediation
145+
146+
# Build payloads from an existing issues list + cached lookups + positions
147+
entries = build_remediation_pack(issues, lookups, positions)
148+
149+
# Dry-run: writes output/remediation_pack_GBR_YYYYMMDD.json + .xlsx
150+
result = apply_remediation(entries, country="GBR", dry_run=True)
151+
152+
print(result.total) # total fixable issues
153+
print(result.skipped) # issues skipped (blank source value, position not found, etc.)
154+
155+
# Each entry includes:
156+
# entry.payload - OData PATCH body: {"code": "POS-123", "division": "DIV-B", "effectiveStartDate": "/Date(ms)/"}
157+
# entry.confidence - HIGH (one valid value) or MEDIUM (multiple valid values, first chosen)
158+
# entry.new_value - the corrected value
159+
```
160+
161+
| Check | Position field corrected | Source |
162+
|-------|--------------------------|--------|
163+
| CHK-01 | `department` | Sub Department's `cust_Department` |
164+
| CHK-02 | `division` | Department's `cust_Division` |
165+
| CHK-03 | `businessUnit` | Division → BU junction |
166+
| CHK-04 | `company` | BU → Legal Entity junction |
167+
| CHK-05 | `costCenter` | Cost Centre → BU junction |
168+
| CHK-06 | `cust_JobFunction` | Job Code's `jobFunction` |
169+
| CHK-07 | `cust_jobSubFunction` | Job Code's `cust_jobsubfunction` |
170+
| CHK-08 | `cust_GlobalJobLevel` | Job Code's `grade` |
171+
| CHK-09 | `cust_CareerPath` | Job Code's `cust_careerPath` |
172+
173+
CHK-10 to CHK-17 (foundation_active checks) are not auto-remediable - they require fixing the foundation record, not the position.
174+
175+
`dry_run=True` is the default. No OData writes are made until `dry_run=False` is explicitly passed with a configured API client.
176+
103177
---
104178

105179
## MCP Server (AI Agent Integration)
@@ -414,18 +488,23 @@ Changes take effect immediately on the next run - no restart needed.
414488
An offline test suite is included - no SF credentials needed:
415489

416490
```bash
417-
python test_schema.py
491+
pytest test_schema.py test_simulator.py test_remediation.py -v
418492
```
419493

420-
Tests cover: SQLite schema structure, CHECK constraints, date normalisation, junction table population, all integrity checks (CHK-01 to CHK-09 pass + fail cases), validation result persistence, audit SQL views, and pipe-separated junction saving.
494+
| Test file | Coverage |
495+
|-----------|---------|
496+
| `test_schema.py` | SQLite schema structure, CHECK constraints, date normalisation, junction table population, all integrity checks (CHK-01 to CHK-09 pass + fail cases), validation result persistence, audit SQL views. |
497+
| `test_simulator.py` | Mode 2 simulation: reparent causes new failures, reparent fixes existing failures, field_change breaks matching positions, zero impact on orphan entity, junction update, result structure, invalid entity/change type errors. |
498+
| `test_remediation.py` | All 9 check types generate correct payloads, HIGH vs MEDIUM confidence, skipped cases (position not found, blank source value), dry-run JSON + Excel output, apply result structure. |
421499

422500
---
423501

424502
## Roadmap
425503

426-
- **Mode 2: Pre-Change Impact Analysis** - simulate a proposed foundation change (e.g. deactivate a Cost Centre, move a Sub Department) and surface every affected Position and Job Info record before the change is applied
504+
- **Mode 2 web UI** - expose the simulation engine and remediation pack builder via the Flask web interface (currently Python API only)
427505
- **Additional check types** - `not_null` rule type and custom expression checks via `rules.yaml`
428506
- **Multi-country parallel runs** - fan out across all active countries in a single execution
507+
- **Live apply** - `dry_run=False` path wired to the web UI with an explicit confirmation step
429508

430509
---
431510

0 commit comments

Comments
 (0)