Adds rows for Standard-Timeclock, CMM, Keyence, Lab, WaxAndTrace,
Genspect, Display, Shopfloor alongside the existing Standard-Machine.
Per-type apps verified against the corresponding v2 manifest's detection
methods (PC-DMIS 2016/2019R2/Protect Viewer/CLM/goCMM for CMM;
VR-6000/USB driver for Keyence; kiosk shortcut for Display).
Common app list deduped via "$ref": "common.<key>" pattern. Verifier
resolves refs into the per-type apps array at runtime so each row stays
short and PCTypes-filter-aware (Lab + Display + Shopfloor get fewer
common apps because the manifest's PCTypes filter excludes them from
FMS hosts pin / Oracle / OpenText respectively).
verify-state.ps1 changes:
- $ref resolution against the matrix.common namespace
- Registry method now permits no DetectionName (key-existence only,
e.g. Protect Viewer)
- New PnpUtilGrep method for INF-driver checks (Keyence USB driver)
Smoke-verified end-to-end on the win11 VM as SYSTEM via qga - 60 checks
across 9 PC types. Type-specific failures (5 CMM, 2 Keyence, 1 Display)
correctly surface "no payload staged" rather than masking it as pass.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Smokes end-to-end on the win11 VM in ~14s for Standard/Machine: 11/11
stage scripts exit 0 (6 Shopfloor baseline + 5 Standard per-PC-type),
transcripts land in C:\Logs\SFLD\ as expected.
Pieces:
- stage-image.ps1 - VM-side: clean prior state, robocopy shopfloor-setup
tree from samba share to C:\Enrollment\shopfloor-setup, drop pc-type +
pc-subtype + site-config, walk numbered stage scripts (^[0-9]{2}-) in
Shopfloor/ then <PCType>/, run each, collect rc + summary. Skips PPKG /
sync_intune / reboot - real machine identity is not touched.
- A-imaging/run.sh - host orchestrator: revert, stage repo tree to
/home/camp/pxe-images/test-stage-A, mount Z: in VM as SYSTEM, invoke
stage-image.ps1 with PCType/PCSubType params, collect transcripts.
Optional PREINSTALL_PATH env if you have the binary installer payload
available; default skips it (00-PreInstall logs "installer not found"
for every entry, expected for orchestration-only test - per-app installs
are covered by Path B).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Harness now passes 9/9 across baseline + heal + idempotent phases on the
win11 VM (Standard/Machine), with 6 drift scenarios applied + healed
between the baseline and heal cycles in ~30s total.
Fixes:
1. lib/qga-run.py - extracted the qga round-trip out of an inline
`python3 - <<PY` heredoc. The inline form clobbered stdin (heredoc
replaces stdin to feed python the script, leaving sys.stdin empty
for the PowerShell snippet the function caller piped in).
2. lib/qga.sh - dropped `set -euo pipefail`. When sourced, it leaked
into the harness shell. Then any captured `out=$(qga_run_ps ...)`
that exited non-zero (verify-state.ps1 returns 1 on any FAIL,
normal during drift phases) would silently abort the harness.
Callers handle non-zero with `|| rc=$?`.
3. B-enforce/run.sh do_verify - rewritten to capture rc, parse summary
line, distinguish expect_pass=true vs false, route to ok / fail
helper without aborting the harness on a normal non-zero verify.
4. matrix.json WJF Defect Tracker entry - switched detection from File
to Registry (uninstall key DisplayVersion). The MSI does not drop
the Defect_Tracker.exe artifact at the documented path even though
the manifest's File detection treats it as installed; the uninstall
reg entry is the reliable install marker. v2 manifest's File
detection path may also need fixing, separate task.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Initial harness scaffolding per SCOPE.md. Drives the win11 analyzer VM
via qemu-guest-agent (runs as NT AUTHORITY\SYSTEM, same context as
GE-Enforce in production - see reference-vm-qga-as-system memory note
for why this is preferred over WinRM).
Pieces:
- lib/qga.sh - host-side helpers (qga round-trip, snapshot revert,
share mount via cmdkey + net use, file upload). Source from any
harness script.
- lib/verify-state.ps1 - VM-side detection runner. Parses matrix.json,
walks each app's verify block, prints PASS/FAIL with detail, exits
0 only if every check passes. Methods: Registry, File, FileVersion,
Hash, FileGrep.
- matrix.json - PC-type matrix data. Currently only Standard/Machine
rows populated (apps + drift scenarios). Extending to other PC types
is just adding rows.
- B-enforce/run.sh - 5-phase orchestrator (stage / baseline / tamper /
heal / idempotent). Defaults to Standard/Machine. SKIP_REVERT=1 for
faster iteration without burning the snapshot revert.
- B-enforce/tamper.ps1 - applies driftScenarios from matrix.json.
Methods: RegRemove, RegSet, FileDelete, FileOverwrite, FileGrepDelete.
Path A (imaging-time install) and remaining 8 PC-type rows are next.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two test paths: (A) imaging-time install via PXE preinstall +
Run-ShopfloorSetup.ps1 per PC type, (B) manifest-engine ongoing
enforcement via GE-Enforce + Install-FromManifest against the v2 share.
Locks the matrix before harness code lands: 9 PC-type rows, expected
install state per type, drift scenarios per app for Path B's
tamper+heal cycle. Decisions: skip JSON CI report (air-gapped solo
workflow), interactive stdout + exit 0/1 only.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Consolidates per-type enforcers (CMM, Keyence, Machine, Common, Acrobat)
into one dispatcher driven by pc-type.txt + site-config and a share-side
manifest layout. Same share is now the single source of truth for routine
software updates without re-imaging.
Runtime:
common/GE-Enforce.ps1 SYSTEM scheduled task. Reads
common/manifest.json plus optional
<pcType>/manifest.json and
<pcType-subType>/manifest.json.
Dispatches each entry through the lib.
Writes _outputs/logs/<hostname>/status.json
on the share after each cycle for fleet
monitoring.
common/Register-GEEnforce.ps1 Task registration. Triggers: AtLogOn +
every 5 min (jittered per-PC from
hostname hash) + daily at 05:45,
13:45, 21:45 EST shift windows.
Unregisters legacy per-type tasks on
install so the two coexist at most for
the duration of a single enforce cycle.
common/Deploy-GEEnforce.ps1 Retrofit helper for already-imaged PCs
(admin-run; copies runtime + registers
task + optional immediate trigger).
Library (common/lib/Install-FromManifest.ps1):
- New Type values: PS1, BAT, File, Registry, INF
- New DetectionMethod values: Always, MarkerFile, ValueMatches, pnputil
- TargetHostnames filter (exact + -like wildcards, ANDed with PCTypes)
- Schema version check (logs WARN on manifest newer than lib MAJOR)
- Auto-writes MarkerFile on successful one-shot PS1/BAT/CMD runs
- MSI log scan on failure surfaces meaningful install errors
- Lib version bumped 2.0 -> 2.1 for TargetHostnames
Observability:
common/monitor-fleet-status.py Scans _outputs/logs/*/status.json for
stale check-ins, failed scopes, and
version drift. Respects scope (dir-name),
PCTypes, and TargetHostnames filters so
entries excluded from a PC do not
false-flag as drift.
Regression harness:
common/test/ Parameterized VM harness + README
covering every action type plus
rollback, bad/missing SFLD creds, and
schema versioning.
Imaging integration:
Run-ShopfloorSetup.ps1 now stages GE-Enforce.ps1 and lib to
C:\Program Files\GE\Shopfloor\ and invokes Register-GEEnforce.ps1
at the end of setup. Legacy Register-CommonEnforce invocation is
kept for the transition; it and the legacy per-type enforcer files
are dead code once Register-GEEnforce runs and will be removed in a
dedicated cleanup pass.
Standard-Machine manifest:
eDNC entry bumped 6.4.3 -> 6.4.5. DetectionValue pinned to the
4-part FileVersion 6.4.5.0 verified against a fresh install in the
Win11 analyzer VM. UDC DetectionValue pinned to 1.0.34 (registry
stores 3-part for UDC; verified live).
scripts/mirror-from-gold.sh:
Restructured around share-root rsyncs (one pass per Samba share)
to close gaps in the prior per-subdir layout: winpeapps/_shared/
Applications (7.5 GB of Adobe + fonts + Java + Office + OpenText
+ printdrivers + wireless + Zscaler), additional winpeapps image
types, and enrollment flat-layout root files. Adds
--skip-clonezilla and --skip-reports.
Verified end-to-end in the Win11 analyzer VM:
- Every action Type and DetectionMethod round-tripped
- PCTypes filter (Oracle excluded on Shopfloor, Firefox included
on Shopfloor and DESKTOP-*, excluded elsewhere)
- TargetHostnames filter (exact, wildcard, no-match)
- Upgrade path: XML hash bump + fleet re-copy
- Rollback path: history-archive restore propagates via enforcer,
fleet converges back without per-PC intervention
- Status writeback + monitor script drift detection
- Graceful degradation on bad creds, missing creds, share
unreachable (all exit 0, log clearly, retry next cycle)
Not in this commit (follow-ups):
- Retire legacy per-type *-Enforce.ps1 files and simplify
09-Setup-*.ps1 scripts (coordinated multi-file cleanup)
- Stage 2b: InUseCheck close-and-reopen, ApplyMode gating,
UpdateWindow, .apply-now.txt sentinel, BITS pre-staging,
1618 mutex retry, PostInstallCheck, Uninstall action
- Management app (manifest CRUD + deploy + rollback + fleet view)
- ShopFloor autologon persistence bug (deferred for next imaging
attempt with live registry evidence)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>