docs(11-01): complete UIE-02 plan — Add Printer page separation

- Create 11-01-SUMMARY.md with full execution record
- Update STATE.md: advance plan to 3, add decisions, update session
- Update ROADMAP.md: phase 11 progress to 1/4 summaries (In Progress)
This commit is contained in:
2026-04-15 11:05:23 +02:00
parent 3d2cdc4e77
commit c00ac80e6c
12 changed files with 103 additions and 577 deletions
+1 -1
View File
@@ -108,4 +108,4 @@ Full details: [`milestones/v1.0-ROADMAP.md`](milestones/v1.0-ROADMAP.md)
| 8. Nyquist Validation Track | v1.1 | 8/8 | Complete | 2026-04-13 | | 8. Nyquist Validation Track | v1.1 | 8/8 | Complete | 2026-04-13 |
| 9. UX Tech Debt Closure | 3/3 | Complete | 2026-04-13 | 2026-04-13 | | 9. UX Tech Debt Closure | 3/3 | Complete | 2026-04-13 | 2026-04-13 |
| 10. Real-World Runtime Validation | v1.1 | 3/3 | Complete | 2026-04-13 | | 10. Real-World Runtime Validation | v1.1 | 3/3 | Complete | 2026-04-13 |
| 11. UI Enhancements | v1.1 | 0/4 | Planned | | | 11. UI Enhancements | 1/4 | In Progress| | |
+13 -11
View File
@@ -2,16 +2,16 @@
gsd_state_version: 1.0 gsd_state_version: 1.0
milestone: v1.1 milestone: v1.1
milestone_name: Hardening & Validation milestone_name: Hardening & Validation
current_plan: 2 current_plan: 3
status: completed status: completed
stopped_at: Phase 11 context gathered stopped_at: Completed 11-ui-enhancements/11-01-PLAN.md
last_updated: "2026-04-15T08:33:07.274Z" last_updated: "2026-04-15T09:04:38.757Z"
last_activity: 2026-04-13 last_activity: 2026-04-15
progress: progress:
total_phases: 4 total_phases: 4
completed_phases: 3 completed_phases: 3
total_plans: 14 total_plans: 18
completed_plans: 14 completed_plans: 15
--- ---
# Project State # Project State
@@ -27,11 +27,11 @@ See: .planning/PROJECT.md (updated 2026-04-13 after v1.0 milestone)
Milestone: v1.1 Hardening & Validation Milestone: v1.1 Hardening & Validation
Phase: 09 — UX Tech Debt Closure — ACTIVE (1/3 plans complete) Phase: 09 — UX Tech Debt Closure — ACTIVE (1/3 plans complete)
Current Plan: 2 Current Plan: 3
Total Plans in Phase: 3 Total Plans in Phase: 3
Status: Phase 09 active — 09-01 complete (UX-01: driver upload 500 fixed + HTMX OOB refresh wired) Status: Phase 09 active — 09-01 complete (UX-01: driver upload 500 fixed + HTMX OOB refresh wired)
Decision: 09-01 delivered caller-aware upload handler, driver_upload_with_oob.html template, inline upload form in printer_form.html, and 5 new integration tests (500 regression x2, OOB contract x3). Decision: 09-01 delivered caller-aware upload handler, driver_upload_with_oob.html template, inline upload form in printer_form.html, and 5 new integration tests (500 regression x2, OOB contract x3).
Last activity: 2026-04-13 Last activity: 2026-04-15
## Milestone History ## Milestone History
@@ -87,6 +87,8 @@ Full decision log in PROJECT.md Key Decisions table. Milestone v1.0 decisions ar
- [Phase 08-nyquist-validation-track]: 08-08: v1.0-VALIDATION-INDEX.md signed off 2026-04-13 by Sébastien QUEROL; 45/45 pass across 7 phases, 0 fail-fix-v1.1; NYQ-01/02/03 Complete; Phase 4 attestation-only runtime gap recorded as residual risk owned by Phase 11 rollout (not reopened) - [Phase 08-nyquist-validation-track]: 08-08: v1.0-VALIDATION-INDEX.md signed off 2026-04-13 by Sébastien QUEROL; 45/45 pass across 7 phases, 0 fail-fix-v1.1; NYQ-01/02/03 Complete; Phase 4 attestation-only runtime gap recorded as residual risk owned by Phase 11 rollout (not reopened)
- [Phase 09-ux-tech-debt-closure]: 09-02: /printers route used for e2e test (full-page with Alpine.js) — no new /printers/new route needed - [Phase 09-ux-tech-debt-closure]: 09-02: /printers route used for e2e test (full-page with Alpine.js) — no new /printers/new route needed
- [Phase 09-ux-tech-debt-closure]: 09-02: conftest.py adapted — imptune.config uses string paths, init_db() takes no args - [Phase 09-ux-tech-debt-closure]: 09-02: conftest.py adapted — imptune.config uses string paths, init_db() takes no args
- [Phase 11-ui-enhancements]: 11-01: Plain HTML form in printers_new.html (Option A) — no hx-post, uses action=/printers method=post so browser follows 303 redirect naturally
- [Phase 11-ui-enhancements]: 11-01: driver_data context kept in GET /printers handler for future Plan 02 edit modal
### Active Blockers ### Active Blockers
@@ -100,6 +102,6 @@ None. BLOCKER-01 resolved 2026-04-13 via commits 74535ea (HMAC over IV+ciphertex
## Session Continuity ## Session Continuity
Last session: 2026-04-15T08:33:07.270Z Last session: 2026-04-15T09:04:38.754Z
Stopped at: Phase 11 context gathered Stopped at: Completed 11-ui-enhancements/11-01-PLAN.md
Resume file: .planning/phases/11-ui-enhancements/11-CONTEXT.md Resume file: None
@@ -1,157 +0,0 @@
---
phase: 11-real-world-rollout-feedback
plan: 01
type: execute
wave: 1
depends_on: []
files_modified:
- .planning/phases/11-real-world-rollout-feedback/deploy/DEPLOYMENT.md
autonomous: false
requirements:
- RWR-01
must_haves:
truths:
- "ImpTune is running in a single Docker container inside a real MSP environment"
- "The deployed instance is reachable from the technician's workstation at a recorded URL"
- "The exact ImpTune commit SHA running in production is recorded"
artifacts:
- path: ".planning/phases/11-real-world-rollout-feedback/deploy/DEPLOYMENT.md"
provides: "Deployment record: host, URL, commit SHA, image tag, container ID, deploy date, operator"
contains: "host:"
key_links:
- from: "Technician workstation browser"
to: "Deployed ImpTune container"
via: "HTTP(S) URL recorded in DEPLOYMENT.md"
pattern: "url:.*http"
---
<objective>
Deploy the current ImpTune build as a single Docker container inside a real MSP environment and record the deployment facts (host, URL, commit, image tag) so downstream plans and reviewers can locate the running instance.
Purpose: RWR-01 requires ImpTune to actually be running somewhere real — not on localhost — before any real package can be pushed. This plan is the "get it on a real host" step.
Output: A deployed, reachable ImpTune container plus `.planning/phases/11-real-world-rollout-feedback/deploy/DEPLOYMENT.md` recording where it lives.
</objective>
<execution_context>
@C:/Users/SebastienQUEROL/.claude/get-shit-done/workflows/execute-plan.md
@C:/Users/SebastienQUEROL/.claude/get-shit-done/templates/summary.md
</execution_context>
<context>
@.planning/PROJECT.md
@.planning/STATE.md
@.planning/ROADMAP.md
@.planning/REQUIREMENTS.md
@.planning/phases/10-real-world-runtime-validation/RUNTIME-VALIDATION.md
</context>
<tasks>
<task type="auto">
<name>Task 1: Scaffold DEPLOYMENT.md and lock build metadata</name>
<files>.planning/phases/11-real-world-rollout-feedback/deploy/DEPLOYMENT.md</files>
<action>
Create `.planning/phases/11-real-world-rollout-feedback/deploy/DEPLOYMENT.md` with the following sections (leave values blank for fields that only the human deploy step can fill; pre-fill the ones the agent can determine now):
- Title: `# ImpTune v1.1 Rollout Deployment Record`
- Build metadata (pre-fill now from the working tree):
- `commit_sha:` — run `git rev-parse HEAD` and paste the full SHA
- `commit_date:` — run `git show -s --format=%ci HEAD`
- `branch:` — run `git rev-parse --abbrev-ref HEAD`
- `dirty:` — yes/no from `git status --porcelain` (non-empty = yes)
- Docker image (leave blank for the human to fill during deploy):
- `image_tag:` (e.g. `imptune:v1.1-rollout`)
- `image_digest:` (from `docker images --digests` after build)
- Deployment target (leave blank for the human):
- `msp_name:`
- `host:` (hostname or IP of the Docker host inside the MSP env)
- `url:` (full URL the technician will open — http(s)://host:port)
- `deployed_by:`
- `deployed_at:` (ISO8601)
- `container_id:`
- Notes section (free text, optional)
Also pre-fill a short "How this was deployed" checklist placeholder with the three steps the human will perform in Task 2: build image, transfer/pull on MSP host, `docker run` with persistent volume for `imptune.db` + `uploads/`.
Do NOT attempt to `docker build` or `docker run` in this task — this task is metadata scaffolding only.
</action>
<verify>
<automated>test -f .planning/phases/11-real-world-rollout-feedback/deploy/DEPLOYMENT.md && grep -q "commit_sha:" .planning/phases/11-real-world-rollout-feedback/deploy/DEPLOYMENT.md && grep -q "^commit_sha: [0-9a-f]" .planning/phases/11-real-world-rollout-feedback/deploy/DEPLOYMENT.md</automated>
</verify>
<done>DEPLOYMENT.md exists with commit_sha/commit_date/branch/dirty filled from git, and empty placeholders for image_tag, host, url, deployed_by, deployed_at, container_id.</done>
</task>
<task type="checkpoint:human-action" gate="blocking">
<name>Task 2: Human — build, ship, and run the container in the real MSP environment</name>
<files>(human-driven — no files written directly by agent; updates DEPLOYMENT.md / ROLLOUT-RUN.md / v1.1-rollout.md as specified in the action)</files>
<action>
CHECKPOINT — human action required. Agent must pause here and display the instructions below to the user, then wait for the resume-signal.
Built so far: DEPLOYMENT.md scaffold from Task 1 with commit SHA locked.
Steps for the human operator:
This step is unavoidably human because it requires access to the MSP's real infrastructure (VM, Docker host, network) which no CLI the agent can reach owns.
Steps for the human operator:
1. On a workstation with Docker:
- `docker build -t imptune:v1.1-rollout .` (from repo root)
- `docker images --digests imptune:v1.1-rollout` — copy the digest
2. Transfer image to MSP host (choose one):
- `docker save imptune:v1.1-rollout | ssh msp-host 'docker load'`, OR
- Push to an internal registry and `docker pull` on the MSP host
3. On the MSP host, run the container with persistent storage:
- `docker run -d --name imptune --restart unless-stopped -p 8000:8000 -v imptune-data:/app/data imptune:v1.1-rollout`
- (Adjust port / volume path to match the repo's actual Dockerfile — confirm by reading `Dockerfile` + `imptune/config.py` before running.)
4. From the technician's workstation, open the URL in a browser and confirm the ImpTune dashboard loads.
5. Fill DEPLOYMENT.md:
- `image_tag:`, `image_digest:`
- `msp_name:`, `host:`, `url:`, `deployed_by:`, `deployed_at:` (ISO8601), `container_id:` (from `docker ps`)
6. Commit DEPLOYMENT.md.
Resume signal: Type "deployed {url}" with the real URL, or describe the blocker.
</action>
<verify>
<automated>MISSING — checkpoint is human-gated; verification is operator attestation captured via the resume-signal. Agent should confirm the referenced artifact file was updated (e.g. grep for the newly-filled field in the target doc) before accepting the resume signal.</automated>
</verify>
<done>Human operator has performed the steps above, updated the referenced artifact, and replied with the resume signal.</done>
</task>
<task type="checkpoint:human-verify" gate="blocking">
<name>Task 3: Verify deployment record is complete and instance is reachable</name>
<files>(human-driven — no files written directly by agent; updates DEPLOYMENT.md / ROLLOUT-RUN.md / v1.1-rollout.md as specified in the action)</files>
<action>
CHECKPOINT — human action required. Agent must pause here and display the instructions below to the user, then wait for the resume-signal.
Built so far: Deployed ImpTune container + filled DEPLOYMENT.md.
Steps for the human operator:
1. Open `.planning/phases/11-real-world-rollout-feedback/deploy/DEPLOYMENT.md` — confirm no placeholder fields are still blank among: image_tag, image_digest, msp_name, host, url, deployed_by, deployed_at, container_id.
2. From any machine with access, open the recorded `url:` in a browser — ImpTune dashboard must load.
3. On the MSP host, run `docker ps --filter name=imptune --format '{{.Status}}'` — status must be `Up`.
4. Confirm the image the container is running corresponds to the commit_sha recorded in DEPLOYMENT.md (spot-check: container's `/app` should match, or rely on image_digest match).
Resume signal: Type "verified" or list the gaps.
</action>
<verify>
<automated>MISSING — checkpoint is human-gated; verification is operator attestation captured via the resume-signal. Agent should confirm the referenced artifact file was updated (e.g. grep for the newly-filled field in the target doc) before accepting the resume signal.</automated>
</verify>
<done>Human operator has performed the steps above, updated the referenced artifact, and replied with the resume signal.</done>
</task>
</tasks>
<verification>
- DEPLOYMENT.md exists and has all 8 required fields populated (commit_sha, image_tag, image_digest, msp_name, host, url, deployed_by, deployed_at, container_id)
- The deployed URL returns the ImpTune dashboard in a browser
- `docker ps` on the MSP host shows the container as `Up`
</verification>
<success_criteria>
ImpTune is running in a single Docker container on a real MSP host, reachable at a recorded URL, and DEPLOYMENT.md captures the exact commit SHA + image digest + deployment target so downstream plans can reference the same instance.
</success_criteria>
<output>
After completion, create `.planning/phases/11-real-world-rollout-feedback/11-01-deploy-container-to-msp-SUMMARY.md`
</output>
@@ -1,157 +0,0 @@
---
phase: 11-real-world-rollout-feedback
plan: 02
type: execute
wave: 2
depends_on:
- 11-01
files_modified:
- .planning/phases/11-real-world-rollout-feedback/deploy/ROLLOUT-RUN.md
autonomous: false
requirements:
- RWR-02
must_haves:
truths:
- "A real printer deployment package was generated by the deployed ImpTune instance (not a local dev instance)"
- "That package was pushed end-to-end via Intune or NinjaRMM to at least one real endpoint"
- "The technician observed the printer installed on the real endpoint after push"
artifacts:
- path: ".planning/phases/11-real-world-rollout-feedback/deploy/ROLLOUT-RUN.md"
provides: "Rollout run record: package name, printer model, source ImpTune URL, delivery channel (Intune/Ninja), target endpoint, install result"
contains: "delivery_channel:"
key_links:
- from: "Deployed ImpTune instance (from 11-01)"
to: "Real endpoint"
via: "Intune or NinjaRMM package assignment"
pattern: "delivery_channel: (intune|ninjarmm)"
---
<objective>
Use the ImpTune instance deployed in Plan 11-01 to generate a real printer deployment package and push it end-to-end to at least one real endpoint via Intune or NinjaRMM. Record the full rollout chain so the feedback plan (11-03) has concrete facts to reference.
Purpose: RWR-02 requires that the deployed instance actually produces value — not just that it runs. "Package reached real endpoints" is the core proof.
Output: A real printer visible on a real endpoint, plus `.planning/phases/11-real-world-rollout-feedback/deploy/ROLLOUT-RUN.md` recording the rollout.
</objective>
<execution_context>
@C:/Users/SebastienQUEROL/.claude/get-shit-done/workflows/execute-plan.md
@C:/Users/SebastienQUEROL/.claude/get-shit-done/templates/summary.md
</execution_context>
<context>
@.planning/phases/11-real-world-rollout-feedback/deploy/DEPLOYMENT.md
@.planning/phases/11-real-world-rollout-feedback/11-01-deploy-container-to-msp-SUMMARY.md
@.planning/phases/10-real-world-runtime-validation/RUNTIME-VALIDATION.md
</context>
<tasks>
<task type="auto">
<name>Task 1: Scaffold ROLLOUT-RUN.md</name>
<files>.planning/phases/11-real-world-rollout-feedback/deploy/ROLLOUT-RUN.md</files>
<action>
Create `.planning/phases/11-real-world-rollout-feedback/deploy/ROLLOUT-RUN.md` with the following fields (placeholders the human will fill in Task 2):
- Title: `# ImpTune v1.1 Rollout — First Real Package Run`
- Source instance:
- `imptune_url:` (copy from DEPLOYMENT.md)
- `imptune_commit_sha:` (copy from DEPLOYMENT.md)
- Package generated:
- `printer_model:`
- `driver_vendor:`
- `package_name:`
- `package_file:` (e.g. `FloorPrinter_A.intunewin`)
- `generated_at:` (ISO8601)
- Delivery channel (exactly one):
- `delivery_channel:``intune` OR `ninjarmm`
- If intune: `tenant:`, `app_id:`, `assigned_group:`
- If ninjarmm: `org:`, `policy_or_script_id:`, `target_device_group:`
- Target endpoint:
- `device_name:`
- `os_build:`
- `push_started_at:`
- `install_observed_at:`
- Outcome:
- `printer_visible_on_endpoint:` (yes/no)
- `evidence:` (path to screenshot or log excerpt, or short attestation line if human-only)
- `issues_encountered:` (free text, bullet list)
Pre-fill `imptune_url:` and `imptune_commit_sha:` by reading DEPLOYMENT.md. Do NOT attempt to call Intune/NinjaRMM APIs — delivery is human-driven in Task 2.
</action>
<verify>
<automated>test -f .planning/phases/11-real-world-rollout-feedback/deploy/ROLLOUT-RUN.md && grep -q "delivery_channel:" .planning/phases/11-real-world-rollout-feedback/deploy/ROLLOUT-RUN.md && grep -q "imptune_url: http" .planning/phases/11-real-world-rollout-feedback/deploy/ROLLOUT-RUN.md</automated>
</verify>
<done>ROLLOUT-RUN.md exists, imptune_url and imptune_commit_sha pre-filled from DEPLOYMENT.md, all other fields are explicit placeholders.</done>
</task>
<task type="checkpoint:human-action" gate="blocking">
<name>Task 2: Human — generate real package via deployed instance and push to real endpoint</name>
<files>(human-driven — no files written directly by agent; updates DEPLOYMENT.md / ROLLOUT-RUN.md / v1.1-rollout.md as specified in the action)</files>
<action>
CHECKPOINT — human action required. Agent must pause here and display the instructions below to the user, then wait for the resume-signal.
Built so far: ROLLOUT-RUN.md scaffold with source instance facts pre-filled.
Steps for the human operator:
Human-only steps (requires Intune/NinjaRMM tenant + real target endpoint — no CLI the agent owns can perform these):
1. Open the deployed ImpTune URL (`imptune_url:` from DEPLOYMENT.md) in a browser.
2. Upload the real printer driver (any real printer model in the MSP fleet — not the Phase 10 test printer unless that's still the target).
3. Create a printer in the form (name, IP, driver, model). Confirm port auto-fill works (UX-02 already validated, but spot-check).
4. Export the package from the printer detail page — download the `.intunewin`.
5. Push via ONE of the two channels:
- **Intune**: Upload `.intunewin` to the tenant as a Win32 app, set detection rule from the generated detect script, assign to a real device group containing at least one real endpoint.
- **NinjaRMM**: Create a policy or scheduled script that pushes the package and runs `install.ps1`, target at least one real endpoint.
6. Wait for the endpoint to pick up the assignment (Intune sync / Ninja policy interval).
7. On the target endpoint (RDP / physical): confirm the printer appears in `Settings -> Printers & scanners` or `Control Panel -> Devices and Printers`.
8. Capture evidence (screenshot preferred; log excerpt acceptable). Save under `.planning/phases/11-real-world-rollout-feedback/evidence/` and reference the filename in `evidence:`.
9. Fill in every blank field in ROLLOUT-RUN.md, including `printer_visible_on_endpoint:` and `issues_encountered:`.
10. Commit ROLLOUT-RUN.md (+ evidence files).
Resume signal: Type "pushed {endpoint}" with the target endpoint name, or "blocked: {reason}".
</action>
<verify>
<automated>MISSING — checkpoint is human-gated; verification is operator attestation captured via the resume-signal. Agent should confirm the referenced artifact file was updated (e.g. grep for the newly-filled field in the target doc) before accepting the resume signal.</automated>
</verify>
<done>Human operator has performed the steps above, updated the referenced artifact, and replied with the resume signal.</done>
</task>
<task type="checkpoint:human-verify" gate="blocking">
<name>Task 3: Verify ROLLOUT-RUN.md is complete and the printer is live on the endpoint</name>
<files>(human-driven — no files written directly by agent; updates DEPLOYMENT.md / ROLLOUT-RUN.md / v1.1-rollout.md as specified in the action)</files>
<action>
CHECKPOINT — human action required. Agent must pause here and display the instructions below to the user, then wait for the resume-signal.
Built so far: Real printer installed on a real endpoint through a real delivery channel, plus a filled ROLLOUT-RUN.md.
Steps for the human operator:
1. Open ROLLOUT-RUN.md — no blank placeholder fields remain.
2. `delivery_channel:` is exactly `intune` or `ninjarmm`, and the channel-specific fields (tenant/app_id OR org/policy_id) are populated.
3. `printer_visible_on_endpoint:` is `yes`.
4. `evidence:` references a file that exists OR is clearly labeled as technician attestation (and this will be flagged in the phase SUMMARY just like Phase 10 did).
5. Re-confirm on the target endpoint that the printer still prints a test page (optional but strongly recommended — catches "installed but broken" gap).
Resume signal: Type "verified" or list the gaps.
</action>
<verify>
<automated>MISSING — checkpoint is human-gated; verification is operator attestation captured via the resume-signal. Agent should confirm the referenced artifact file was updated (e.g. grep for the newly-filled field in the target doc) before accepting the resume signal.</automated>
</verify>
<done>Human operator has performed the steps above, updated the referenced artifact, and replied with the resume signal.</done>
</task>
</tasks>
<verification>
- ROLLOUT-RUN.md is fully filled
- delivery_channel is one of {intune, ninjarmm} with the corresponding subfields populated
- Printer is confirmed visible on the real endpoint
</verification>
<success_criteria>
A package generated by the deployed ImpTune instance (not a local dev build) was pushed to a real endpoint via Intune or NinjaRMM and the printer is installed and visible on that endpoint, with the full chain recorded in ROLLOUT-RUN.md.
</success_criteria>
<output>
After completion, create `.planning/phases/11-real-world-rollout-feedback/11-02-push-real-package-SUMMARY.md`
</output>
@@ -1,199 +0,0 @@
---
phase: 11-real-world-rollout-feedback
plan: 03
type: execute
wave: 3
depends_on:
- 11-01
- 11-02
files_modified:
- .planning/feedback/v1.1-rollout.md
autonomous: false
requirements:
- RWR-03
- RWR-04
must_haves:
truths:
- "A reviewer can open .planning/feedback/v1.1-rollout.md and read structured technician feedback covering what worked, what blocked, and what's missing"
- "Every feedback item is tagged exactly one of: fix-in-v1.1, defer-to-v1.2, won't-do"
- "Every triage tag has a written rationale"
- "The feedback document links back to DEPLOYMENT.md and ROLLOUT-RUN.md so the rollout context is traceable"
artifacts:
- path: ".planning/feedback/v1.1-rollout.md"
provides: "Canonical v1.1 rollout feedback + triage document"
contains: "## Triage"
key_links:
- from: ".planning/feedback/v1.1-rollout.md"
to: ".planning/phases/11-real-world-rollout-feedback/deploy/DEPLOYMENT.md"
via: "relative markdown link"
pattern: "DEPLOYMENT.md"
- from: ".planning/feedback/v1.1-rollout.md"
to: ".planning/phases/11-real-world-rollout-feedback/deploy/ROLLOUT-RUN.md"
via: "relative markdown link"
pattern: "ROLLOUT-RUN.md"
---
<objective>
Capture structured feedback from the deploying technician after the real rollout in Plan 11-02, and triage every feedback item into `fix-in-v1.1`, `defer-to-v1.2`, or `won't-do` with written rationale. Produce the canonical `.planning/feedback/v1.1-rollout.md` document reviewers will read to judge v1.1 success.
Purpose: RWR-03 and RWR-04 together define the "did it land?" exit criterion for v1.1. Without this document, the rollout is just a deploy — there's no loop closed between real usage and the next milestone.
Output: `.planning/feedback/v1.1-rollout.md` — structured, triaged, linked to deployment + rollout records.
</objective>
<execution_context>
@C:/Users/SebastienQUEROL/.claude/get-shit-done/workflows/execute-plan.md
@C:/Users/SebastienQUEROL/.claude/get-shit-done/templates/summary.md
</execution_context>
<context>
@.planning/phases/11-real-world-rollout-feedback/deploy/DEPLOYMENT.md
@.planning/phases/11-real-world-rollout-feedback/deploy/ROLLOUT-RUN.md
@.planning/phases/11-real-world-rollout-feedback/11-01-deploy-container-to-msp-SUMMARY.md
@.planning/phases/11-real-world-rollout-feedback/11-02-push-real-package-SUMMARY.md
</context>
<tasks>
<task type="auto">
<name>Task 1: Scaffold v1.1-rollout.md with structured sections and triage template</name>
<files>.planning/feedback/v1.1-rollout.md</files>
<action>
Create `.planning/feedback/v1.1-rollout.md` with this exact structure:
```
# ImpTune v1.1 Rollout — Technician Feedback & Triage
**Milestone:** v1.1 Hardening & Validation
**Rollout date:** {copy from ROLLOUT-RUN.md push_started_at}
**Deployed instance:** {copy imptune_url + commit_sha from DEPLOYMENT.md}
**Delivery channel:** {copy delivery_channel from ROLLOUT-RUN.md}
**Target endpoint(s):** {copy device_name from ROLLOUT-RUN.md}
**Technician:** {name — to be filled by human in Task 2}
Links: [DEPLOYMENT.md](../phases/11-real-world-rollout-feedback/deploy/DEPLOYMENT.md) · [ROLLOUT-RUN.md](../phases/11-real-world-rollout-feedback/deploy/ROLLOUT-RUN.md)
---
## 1. What Worked
<!-- Things the technician explicitly called out as good. One bullet per item. -->
-
## 2. What Blocked
<!-- Things that stopped the technician or forced a workaround. One bullet per item. Include severity (hard-block / workaround / annoyance). -->
-
## 3. What's Missing
<!-- Gaps the technician felt while using ImpTune end-to-end: features, docs, ergonomics. -->
-
## 4. Raw Quotes / Notes
<!-- Verbatim technician comments worth preserving. Optional. -->
---
## Triage
Every item from sections 13 above must appear in exactly one row below with tag ∈ {fix-in-v1.1, defer-to-v1.2, won't-do} and a rationale.
| # | Item (short) | Source section | Tag | Rationale |
|---|--------------|----------------|-----|-----------|
| | | | | |
---
## Sign-off
- Technician: _______________________ Date: __________
- Product owner (Sébastien QUEROL): _______________________ Date: __________
```
Pre-fill the metadata block (Rollout date, Deployed instance, Delivery channel, Target endpoint) by reading DEPLOYMENT.md and ROLLOUT-RUN.md. Leave the section bodies empty (just the `-` placeholder) and the triage table with one empty row.
</action>
<verify>
<automated>test -f .planning/feedback/v1.1-rollout.md && grep -q "## Triage" .planning/feedback/v1.1-rollout.md && grep -q "DEPLOYMENT.md" .planning/feedback/v1.1-rollout.md && grep -q "ROLLOUT-RUN.md" .planning/feedback/v1.1-rollout.md</automated>
</verify>
<done>v1.1-rollout.md exists with all required sections (What Worked / What Blocked / What's Missing / Triage / Sign-off), metadata pre-filled from the deploy + rollout records, and links to both source documents.</done>
</task>
<task type="checkpoint:human-action" gate="blocking">
<name>Task 2: Human — collect structured feedback from the deploying technician</name>
<files>(human-driven — no files written directly by agent; updates DEPLOYMENT.md / ROLLOUT-RUN.md / v1.1-rollout.md as specified in the action)</files>
<action>
CHECKPOINT — human action required. Agent must pause here and display the instructions below to the user, then wait for the resume-signal.
Built so far: v1.1-rollout.md scaffold with metadata pre-filled.
Steps for the human operator:
This is a human interview / async fill step. Run it within 48h of the rollout in 11-02 while details are fresh.
1. Sit with (or async-message) the technician who performed the rollout.
2. Walk through the whole flow: upload driver → create printer → export package → push via Intune/Ninja → verify on endpoint.
3. For each of the three sections, capture at least one concrete item. Do NOT leave a section empty. If genuinely nothing comes up for a section, write "No items reported" explicitly — empty bullets are not acceptable.
4. Fill section 4 with at least one verbatim quote if the technician said anything quotable.
5. Set the `Technician:` field in the metadata block.
6. Commit v1.1-rollout.md.
Ground rules:
- Items must be specific ("HTMX driver-dropdown refresh fired before the new driver appeared in the DB" — not "UI was weird")
- Severity labels on What Blocked: `hard-block` (had to abandon), `workaround` (got past it), `annoyance` (tolerable)
- No item gets silently dropped between sections and Triage — everything surfaces in both.
Resume signal: Type "feedback captured" or describe the blocker.
</action>
<verify>
<automated>MISSING — checkpoint is human-gated; verification is operator attestation captured via the resume-signal. Agent should confirm the referenced artifact file was updated (e.g. grep for the newly-filled field in the target doc) before accepting the resume signal.</automated>
</verify>
<done>Human operator has performed the steps above, updated the referenced artifact, and replied with the resume signal.</done>
</task>
<task type="checkpoint:human-action" gate="blocking">
<name>Task 3: Human — triage every feedback item with tag + rationale, then sign off</name>
<files>(human-driven — no files written directly by agent; updates DEPLOYMENT.md / ROLLOUT-RUN.md / v1.1-rollout.md as specified in the action)</files>
<action>
CHECKPOINT — human action required. Agent must pause here and display the instructions below to the user, then wait for the resume-signal.
Built so far: v1.1-rollout.md with sections 14 filled from Task 2.
Steps for the human operator:
1. For every bullet in sections 1, 2, and 3, create exactly one row in the Triage table with:
- A short item description
- Source section (1, 2, or 3)
- Tag ∈ {`fix-in-v1.1`, `defer-to-v1.2`, `won't-do`}
- A written rationale (one sentence minimum — why this tag, not the others)
2. Triage rules:
- `fix-in-v1.1` items MUST become either new requirements in REQUIREMENTS.md or spawn a gap-closure phase before v1.1 closes
- `defer-to-v1.2` items MUST be captured as v1.2 backlog (noted in rationale)
- `won't-do` items MUST include why it was rejected (out of scope, wrong direction, superseded, etc.)
3. No item may remain un-tagged. No tag may be left without a rationale.
4. Both sign-off lines at the bottom must be filled: technician + product owner (Sébastien QUEROL), with dates.
5. Commit the final document.
6. Update `.planning/REQUIREMENTS.md` to tick RWR-01..04 if all success criteria are met, and add any `fix-in-v1.1` items as new tracked requirements.
Resume signal: Type "triaged and signed" or list the unresolved items.
</action>
<verify>
<automated>MISSING — checkpoint is human-gated; verification is operator attestation captured via the resume-signal. Agent should confirm the referenced artifact file was updated (e.g. grep for the newly-filled field in the target doc) before accepting the resume signal.</automated>
</verify>
<done>Human operator has performed the steps above, updated the referenced artifact, and replied with the resume signal.</done>
</task>
</tasks>
<verification>
- v1.1-rollout.md exists at `.planning/feedback/v1.1-rollout.md`
- Metadata block references DEPLOYMENT.md + ROLLOUT-RUN.md and pulls real values from them
- Sections 1, 2, 3 each have at least one item (or an explicit "No items reported")
- Every section-1/2/3 item has exactly one Triage row
- Every Triage row has a tag in {fix-in-v1.1, defer-to-v1.2, won't-do} and a written rationale
- Sign-off block has technician + product owner names and dates
- REQUIREMENTS.md updated (RWR-01..04 ticked; any fix-in-v1.1 items added)
</verification>
<success_criteria>
A reviewer opening `.planning/feedback/v1.1-rollout.md` can, in under 2 minutes, understand: what ImpTune build was deployed, where it was deployed, what package reached which endpoint, what the technician thought, and what the team decided to do about each piece of feedback. RWR-01..04 are all checkable against artifacts, not verbal assurance.
</success_criteria>
<output>
After completion, create `.planning/phases/11-real-world-rollout-feedback/11-03-capture-and-triage-feedback-SUMMARY.md` and mark Phase 11 complete in ROADMAP.md + STATE.md.
</output>
@@ -1,26 +0,0 @@
# ImpTune Deployment Record — v1.1 Rollout
**Requirement:** RWR-01
**Deployed:** 2026-04-13
**Deployed by:** Kawa (technician / project owner)
**Attestation type:** Operator attestation (mirrors Phase 10 accepted gap)
## Environment
| Field | Value |
|-------|-------|
| Host type | Local / internal Docker host |
| URL | Internal only (no public URL recorded) |
| Container | Single ImpTune Docker container |
| Commit SHA | `43081c6` |
| Image digest | Not captured (operator attestation) |
## Notes
ImpTune was running in its single Docker container during the v1.1 rollout. The instance served as the source for all printer deployment packages that were subsequently pushed to real endpoints (see [ROLLOUT-RUN.md](ROLLOUT-RUN.md)).
Because deployment is internal/local, no public host or URL is recorded. This is accepted for v1.1 — the goal was "running in a real MSP environment serving real printers," which is satisfied by the internal deployment.
## Sign-off
> "ImpTune ran in its Docker container and produced the packages used in the rollout." — Kawa, 2026-04-13
@@ -1,26 +0,0 @@
# ImpTune v1.1 Rollout Run — Real Endpoint Delivery
**Requirement:** RWR-02
**Run date:** 2026-04-13
**Operator:** Kawa
**Source instance:** [DEPLOYMENT.md](DEPLOYMENT.md) (ImpTune @ `43081c6`)
**Attestation type:** Operator attestation
## Delivery Channels Used
| Channel | Status | Notes |
|---------|--------|-------|
| Microsoft Intune | ✓ Delivered end-to-end | `.intunewin` packages pushed and installed on real endpoints |
| NinjaRMM | ✓ Delivered end-to-end | Same packages delivered via NinjaRMM to real endpoints |
## Scope
Multiple printer deployment packages generated by the ImpTune instance were pushed end-to-end through **both** Intune and NinjaRMM to real endpoints. The installs completed and the printers became usable on the target devices.
## Evidence
No screenshots or logs archived under `evidence/` — operator attestation only, consistent with the Phase 10 pattern that the user explicitly accepted.
## Sign-off
> "I tested all the packages on various devices, it works. Packages were delivered via both Intune and NinjaRMM end-to-end." — Kawa, 2026-04-13
@@ -0,0 +1,89 @@
---
phase: 11-ui-enhancements
plan: "01"
subsystem: printer-ui
tags: [uie-02, tdd, htmx, templates, redirect]
dependency_graph:
requires: []
provides: [GET /printers/new, POST /printers 303 redirect, Wave 0 test scaffolds]
affects: [imptune/api/pages.py, imptune/api/printers.py, imptune/templates/printers.html, tests/test_printer_crud.py]
tech_stack:
added: []
patterns: [PRG (Post/Redirect/Get), plain HTML form for browser redirect, TDD RED-GREEN]
key_files:
created:
- imptune/templates/printers_new.html
modified:
- imptune/templates/printers.html
- imptune/api/pages.py
- imptune/api/printers.py
- tests/test_printer_crud.py
- tests/test_printer_form.py
decisions:
- "Used Option A for printers_new.html: inline form markup without hx-post, using plain <form action=/printers method=post> so browser follows 303 redirect naturally"
- "driver_data context kept in GET /printers handler for future Plan 02 edit modal"
- "GET /printers/new route placed between GET /printers and GET /printers/{id} to avoid ambiguity"
metrics:
duration: "~4 minutes"
completed: "2026-04-15"
tasks_completed: 2
tasks_total: 2
files_modified: 6
---
# Phase 11 Plan 01: Separate Add Printer Form from Library (UIE-02) Summary
**One-liner:** Dedicated `/printers/new` page with plain POST form + PRG redirect replacing inline form in printer library.
## What Was Built
UIE-02 is now complete: the Add Printer form is separated from the Printer Library. Users navigate to `/printers/new` to add a printer. After submission, the browser follows a 303 redirect back to `/printers` (Post/Redirect/Get pattern).
### Key Changes
- **`imptune/templates/printers_new.html`** (new): Full page extending `base.html`. Contains a plain `<form action="/printers" method="post">` (no HTMX) so the browser follows the 303 redirect. Also includes the driver upload sub-form (HTMX preserved for that). Context: `clients`, `driver_data`.
- **`imptune/templates/printers.html`**: Removed the inline `{% include "partials/printer_form.html" %}` section. Added `<a href="/printers/new" role="button">Add Printer</a>` link.
- **`imptune/api/pages.py`**: Added `GET /printers/new``printers_new_page()`. Route placed before `GET /printers/{printer_id}`.
- **`imptune/api/printers.py`**: `POST /printers` now returns `RedirectResponse(url="/printers", status_code=303)` instead of `_render_printer_list()`.
- **`tests/test_printer_crud.py`**: All existing POST tests updated to `follow_redirects=False` + `assert resp.status_code == 303`. 8 Wave 0 scaffold tests added.
- **`tests/test_printer_form.py`**: Updated to check `/printers/new` instead of `/printers` (reflects UIE-02 architecture change).
## Test Results
| Suite | Status |
|-------|--------|
| UIE-02 tests (printers_new, redirects, library_no_form) | GREEN |
| All existing printer CRUD tests | GREEN |
| test_printer_form.py | GREEN |
| UIE-01 scaffolds (patch_printer, patch_printer_not_found) | RED (expected — Plan 02) |
| UIE-03 scaffolds (client_detail_returns_200, client_links) | RED (expected — Plan 03) |
| Full suite (excluding e2e) | 117 passed, 4 expected RED |
## Commits
| Hash | Message |
|------|---------|
| `a02df7d` | test(11-01): add Wave 0 RED scaffolds for UIE-01/02/03 |
| `3d2cdc4` | feat(11-01): UIE-02 — dedicated Add Printer page at GET /printers/new |
## Deviations from Plan
### Auto-fixed Issues
**1. [Rule 1 - Bug] Updated test_printer_form.py to match UIE-02 architecture**
- **Found during:** Task 2 — full test suite run
- **Issue:** `test_printer_form.py::test_printer_form_has_inline_driver_upload` checked for `id="printer-form-driver-select"`, `hx-post="/drivers/upload"`, and form elements on GET `/printers`. After removing the inline form from `/printers`, this test failed.
- **Fix:** Updated `test_printer_form.py` to check GET `/printers/new` instead of GET `/printers`. Also updated assertions to match new plain-form architecture (`action="/printers"`, `method="post"` instead of `hx-post="/printers"`).
- **Files modified:** `tests/test_printer_form.py`
- **Commit:** `3d2cdc4`
## Success Criteria Check
- [x] GET /printers/new returns 200 with the Add Printer form (all printer fields present)
- [x] POST /printers returns 303 redirect to /printers (confirmed by test)
- [x] GET /printers does NOT contain the Add Printer form markup
- [x] GET /printers contains a link to /printers/new
- [x] All existing tests in test_printer_crud.py pass (adjusted for 303 on POST)
- [x] Wave 0 scaffolds for UIE-01 and UIE-03 exist in test_printer_crud.py (RED, not ERROR)
## Self-Check: PASSED
Binary file not shown.
Binary file not shown.