docs(04-01): complete script generator install plan summary
- SUMMARY.md for phase 04 plan 01 (TDD install script generator) - STATE.md: progress updated to 89%, decisions recorded, session updated - ROADMAP.md: phase 4 plan progress updated (1/2 summaries) - REQUIREMENTS.md: SCRPT-01, SCRPT-04, SCRPT-05 marked complete
This commit is contained in:
@@ -30,11 +30,11 @@ Requirements for initial release. Each maps to roadmap phases.
|
|||||||
|
|
||||||
### Script Generation
|
### Script Generation
|
||||||
|
|
||||||
- [ ] **SCRPT-01**: System generates PowerShell install script (pnputil staging + Add-PrinterPort + Add-PrinterDriver + Add-Printer + Set-PrintConfiguration)
|
- [x] **SCRPT-01**: System generates PowerShell install script (pnputil staging + Add-PrinterPort + Add-PrinterDriver + Add-Printer + Set-PrintConfiguration)
|
||||||
- [ ] **SCRPT-02**: System generates PowerShell uninstall script (Remove-Printer + Remove-PrinterDriver + Remove-PrinterPort)
|
- [ ] **SCRPT-02**: System generates PowerShell uninstall script (Remove-Printer + Remove-PrinterDriver + Remove-PrinterPort)
|
||||||
- [ ] **SCRPT-03**: System generates Intune detection script (registry check for printer name)
|
- [ ] **SCRPT-03**: System generates Intune detection script (registry check for printer name)
|
||||||
- [ ] **SCRPT-04**: Generated install script detects SYSTEM vs. user context and self-elevates via UAC when run by user
|
- [x] **SCRPT-04**: Generated install script detects SYSTEM vs. user context and self-elevates via UAC when run by user
|
||||||
- [ ] **SCRPT-05**: Generated install script includes 64-bit WOW64 relaunch guard for Intune's 32-bit execution context
|
- [x] **SCRPT-05**: Generated install script includes 64-bit WOW64 relaunch guard for Intune's 32-bit execution context
|
||||||
|
|
||||||
### Package Export
|
### Package Export
|
||||||
|
|
||||||
@@ -100,11 +100,11 @@ Which phases cover which requirements. Updated during roadmap creation.
|
|||||||
| PRNT-08 | Phase 3 | Complete |
|
| PRNT-08 | Phase 3 | Complete |
|
||||||
| PRNT-09 | Phase 3 | Complete |
|
| PRNT-09 | Phase 3 | Complete |
|
||||||
| PRNT-10 | Phase 3 | Complete |
|
| PRNT-10 | Phase 3 | Complete |
|
||||||
| SCRPT-01 | Phase 4 | Pending |
|
| SCRPT-01 | Phase 4 | Complete |
|
||||||
| SCRPT-02 | Phase 4 | Pending |
|
| SCRPT-02 | Phase 4 | Pending |
|
||||||
| SCRPT-03 | Phase 4 | Pending |
|
| SCRPT-03 | Phase 4 | Pending |
|
||||||
| SCRPT-04 | Phase 4 | Pending |
|
| SCRPT-04 | Phase 4 | Complete |
|
||||||
| SCRPT-05 | Phase 4 | Pending |
|
| SCRPT-05 | Phase 4 | Complete |
|
||||||
| PKG-01 | Phase 5 | Pending |
|
| PKG-01 | Phase 5 | Pending |
|
||||||
| PKG-02 | Phase 5 | Pending |
|
| PKG-02 | Phase 5 | Pending |
|
||||||
| PKG-03 | Phase 5 | Pending |
|
| PKG-03 | Phase 5 | Pending |
|
||||||
|
|||||||
@@ -108,5 +108,5 @@ Phases execute in numeric order: 1 → 2 → 3 → 4 → 5
|
|||||||
| 1. Foundation | 3/3 | Complete | 2026-04-10 |
|
| 1. Foundation | 3/3 | Complete | 2026-04-10 |
|
||||||
| 2. Driver Management | 1/2 | In Progress| |
|
| 2. Driver Management | 1/2 | In Progress| |
|
||||||
| 3. Printer Configuration | 2/2 | Complete | 2026-04-10 |
|
| 3. Printer Configuration | 2/2 | Complete | 2026-04-10 |
|
||||||
| 4. Script Generation | 0/2 | Not started | - |
|
| 4. Script Generation | 1/2 | In Progress| |
|
||||||
| 5. Package Export | 0/3 | Not started | - |
|
| 5. Package Export | 0/3 | Not started | - |
|
||||||
|
|||||||
+8
-6
@@ -3,14 +3,14 @@ gsd_state_version: 1.0
|
|||||||
milestone: v1.0
|
milestone: v1.0
|
||||||
milestone_name: milestone
|
milestone_name: milestone
|
||||||
status: executing
|
status: executing
|
||||||
stopped_at: Completed 03-02-PLAN.md
|
stopped_at: Completed 04-01-PLAN.md
|
||||||
last_updated: "2026-04-10T11:14:33.220Z"
|
last_updated: "2026-04-10T11:32:55.889Z"
|
||||||
last_activity: "2026-04-10 — Plan 01-01 complete: Docker scaffold, FastAPI app shell, sidebar templates, 3-test green suite"
|
last_activity: "2026-04-10 — Plan 01-01 complete: Docker scaffold, FastAPI app shell, sidebar templates, 3-test green suite"
|
||||||
progress:
|
progress:
|
||||||
total_phases: 5
|
total_phases: 5
|
||||||
completed_phases: 3
|
completed_phases: 3
|
||||||
total_plans: 7
|
total_plans: 9
|
||||||
completed_plans: 7
|
completed_plans: 8
|
||||||
percent: 7
|
percent: 7
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -55,6 +55,7 @@ Progress: [░░░░░░░░░░] 7%
|
|||||||
| Phase 02-driver-management P02-02 | 3 | 2 tasks | 7 files |
|
| Phase 02-driver-management P02-02 | 3 | 2 tasks | 7 files |
|
||||||
| Phase 03-printer-configuration P01 | 7 | 2 tasks | 12 files |
|
| Phase 03-printer-configuration P01 | 7 | 2 tasks | 12 files |
|
||||||
| Phase 03-printer-configuration P02 | 2 | 2 tasks | 4 files |
|
| Phase 03-printer-configuration P02 | 2 | 2 tasks | 4 files |
|
||||||
|
| Phase 04-script-generation P01 | 2 | 1 tasks | 3 files |
|
||||||
|
|
||||||
## Accumulated Context
|
## Accumulated Context
|
||||||
|
|
||||||
@@ -83,6 +84,7 @@ Recent decisions affecting current work:
|
|||||||
- [Phase 03-printer-configuration]: Alpine.js portEdited guard prevents port overwrite after manual edit (PRNT-03)
|
- [Phase 03-printer-configuration]: Alpine.js portEdited guard prevents port overwrite after manual edit (PRNT-03)
|
||||||
- [Phase 03-02]: Detail page is a full-page template (not partial) — simpler than partial injection into printers.html
|
- [Phase 03-02]: Detail page is a full-page template (not partial) — simpler than partial injection into printers.html
|
||||||
- [Phase 03-02]: Route lives in pages.py (not printers.py) because it returns a full HTML page, not an HTMX fragment
|
- [Phase 03-02]: Route lives in pages.py (not printers.py) because it returns a full HTML page, not an HTMX fragment
|
||||||
|
- [Phase 04-script-generation]: render_install() takes plain string args (not ORM object) for DB-free unit testability; _duplex_map translates LongEdge->TwoSidedLongEdge before template rendering
|
||||||
|
|
||||||
### Pending Todos
|
### Pending Todos
|
||||||
|
|
||||||
@@ -95,6 +97,6 @@ None yet.
|
|||||||
|
|
||||||
## Session Continuity
|
## Session Continuity
|
||||||
|
|
||||||
Last session: 2026-04-10T11:05:44.949Z
|
Last session: 2026-04-10T11:32:55.884Z
|
||||||
Stopped at: Completed 03-02-PLAN.md
|
Stopped at: Completed 04-01-PLAN.md
|
||||||
Resume file: None
|
Resume file: None
|
||||||
|
|||||||
@@ -0,0 +1,105 @@
|
|||||||
|
---
|
||||||
|
phase: 04-script-generation
|
||||||
|
plan: "01"
|
||||||
|
subsystem: script-generator
|
||||||
|
tags: [jinja2, powershell, tdd, wow64, uac, pnputil, idempotency]
|
||||||
|
one_liner: "Jinja2-based install.ps1 generator with WOW64 guard, UAC elevation, pnputil two-step, and duplex mapping"
|
||||||
|
dependency_graph:
|
||||||
|
requires: []
|
||||||
|
provides: [render_install, install.ps1.j2]
|
||||||
|
affects: [imptune.generators.script_generator, imptune.templates.scripts]
|
||||||
|
tech_stack:
|
||||||
|
added: []
|
||||||
|
patterns:
|
||||||
|
- Jinja2 FileSystemLoader with trim_blocks + lstrip_blocks for PowerShell templates
|
||||||
|
- Plain-string function parameters for DB-free unit testability
|
||||||
|
- _duplex_map translation dict (model values -> PowerShell cmdlet values)
|
||||||
|
key_files:
|
||||||
|
created:
|
||||||
|
- imptune/generators/script_generator.py
|
||||||
|
- imptune/templates/scripts/install.ps1.j2
|
||||||
|
- tests/test_script_generator.py
|
||||||
|
modified: []
|
||||||
|
decisions:
|
||||||
|
- "render_install() takes plain string args (not ORM Printer object) — keeps tests DB-free"
|
||||||
|
- "Boolean color_mode/collate converted to lowercase 'true'/'false' strings; template adds $ prefix"
|
||||||
|
- "_duplex_map translates before rendering: LongEdge->TwoSidedLongEdge, ShortEdge->TwoSidedShortEdge"
|
||||||
|
- "WOW64 guard comment avoids 'pnputil.exe' text to preserve ordering assertion in test"
|
||||||
|
metrics:
|
||||||
|
duration: "~2 min"
|
||||||
|
completed_date: "2026-04-10"
|
||||||
|
tasks_completed: 1
|
||||||
|
files_created: 3
|
||||||
|
files_modified: 0
|
||||||
|
tests_added: 7
|
||||||
|
tests_passing: 68
|
||||||
|
---
|
||||||
|
|
||||||
|
# Phase 4 Plan 01: Script Generator (Install) Summary
|
||||||
|
|
||||||
|
**One-liner:** Jinja2-based install.ps1 generator with WOW64 guard, UAC elevation, pnputil two-step, and duplex mapping
|
||||||
|
|
||||||
|
## What Was Built
|
||||||
|
|
||||||
|
A TDD-developed module `imptune/generators/script_generator.py` with a single public function `render_install()` that renders the `install.ps1.j2` Jinja2 template into a complete, production-ready PowerShell printer install script.
|
||||||
|
|
||||||
|
### render_install() function
|
||||||
|
|
||||||
|
- Takes plain string arguments (no ORM dependency) for easy unit testing
|
||||||
|
- Translates `duplex_mode` via `_duplex_map` before passing to template
|
||||||
|
- Converts Python booleans to lowercase strings (`"true"`/`"false"`) for PowerShell `$true`/`$false` rendering
|
||||||
|
|
||||||
|
### install.ps1.j2 template structure (in order)
|
||||||
|
|
||||||
|
1. Header comment with printer name and required Intune install command
|
||||||
|
2. WOW64 guard (`$env:PROCESSOR_ARCHITECTURE` + `SysNative` relaunch) — FIRST executable block
|
||||||
|
3. SYSTEM vs admin detection (`[WindowsIdentity]::GetCurrent()`, `IsSystem`, `IsInRole(Administrator)`) + UAC self-elevation via `Start-Process -Verb Runas`
|
||||||
|
4. pnputil two-step: `/add-driver` to stage INF, then `Add-PrinterDriver` to register
|
||||||
|
5. Idempotent port creation: `Get-PrinterPort` check before `Add-PrinterPort`
|
||||||
|
6. Idempotent printer creation: `Get-Printer` check before `Add-Printer`
|
||||||
|
7. `Set-PrintConfiguration` with translated duplex, color, paper size, collate
|
||||||
|
|
||||||
|
## TDD Execution
|
||||||
|
|
||||||
|
### RED Phase (commit b4f2c64)
|
||||||
|
|
||||||
|
7 tests written in `tests/test_script_generator.py` covering SCRPT-01, SCRPT-04, SCRPT-05. All failed with `ModuleNotFoundError` (confirmed RED).
|
||||||
|
|
||||||
|
### GREEN Phase (commit 8193e9d)
|
||||||
|
|
||||||
|
- `imptune/generators/script_generator.py` created
|
||||||
|
- `imptune/templates/scripts/install.ps1.j2` created
|
||||||
|
|
||||||
|
One auto-fix required during GREEN: template comment contained `"pnputil.exe"` before the WOW64 `PROCESSOR_ARCHITECTURE` check text, causing the ordering assertion in `test_render_install_wow64_guard` to fail. Fixed by removing `.exe` from the comment text. Not a logic error — purely a textual ordering issue in the rendered output.
|
||||||
|
|
||||||
|
All 7 new tests pass. Full suite: 68/68 passing.
|
||||||
|
|
||||||
|
## Commits
|
||||||
|
|
||||||
|
| Hash | Type | Description |
|
||||||
|
|------|------|-------------|
|
||||||
|
| b4f2c64 | test | RED phase — 7 failing tests for script_generator |
|
||||||
|
| 8193e9d | feat | GREEN phase — script_generator.py + install.ps1.j2 |
|
||||||
|
|
||||||
|
## Deviations from Plan
|
||||||
|
|
||||||
|
### Auto-fixed Issues
|
||||||
|
|
||||||
|
**1. [Rule 1 - Bug] Template comment contained 'pnputil.exe' before WOW64 guard text**
|
||||||
|
- **Found during:** GREEN phase test run
|
||||||
|
- **Issue:** Comment in the WOW64 guard block header said "pnputil.exe is 64-bit only", so the string "pnputil.exe" appeared in the rendered output before "PROCESSOR_ARCHITECTURE", breaking the ordering assertion in `test_render_install_wow64_guard`
|
||||||
|
- **Fix:** Changed "pnputil.exe is 64-bit only" to "pnputil is 64-bit only" in the template comment
|
||||||
|
- **Files modified:** `imptune/templates/scripts/install.ps1.j2`
|
||||||
|
- **Commit:** 8193e9d (included in same GREEN commit)
|
||||||
|
|
||||||
|
## Self-Check: PASSED
|
||||||
|
|
||||||
|
All created files verified on disk. All commits verified in git log.
|
||||||
|
|
||||||
|
| Item | Status |
|
||||||
|
|------|--------|
|
||||||
|
| imptune/generators/script_generator.py | FOUND |
|
||||||
|
| imptune/templates/scripts/install.ps1.j2 | FOUND |
|
||||||
|
| tests/test_script_generator.py | FOUND |
|
||||||
|
| Commit b4f2c64 (RED) | FOUND |
|
||||||
|
| Commit 8193e9d (GREEN) | FOUND |
|
||||||
Reference in New Issue
Block a user