psadt-deploy-skill 0.44.0 → 0.47.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -73,7 +73,7 @@ Thirteen phases, each owned by a script rather than by prose, so a step either p
73
73
  | **1-2** Intake + research | blocker questions as clickable options; a local-evidence ladder (installed here? binary here? already written down?) answers what it can, and a research agent is dispatched only per question it leaves open | agent (gates 1-2) |
74
74
  | **3** Scaffold | a generator writes launcher + detection + per-run log name + manifest | `New-MsiPackage` · `New-ExePackage` · `New-BrowserExtensionPackage` · `New-WindowsFeaturePackage` · `New-DriverPackage` |
75
75
  | **4** Customize | all three hooks filled from the research, helpers in the Extensions module | agent |
76
- | **5** Pre-flight | 11 checks (encoding, AST parse, v3 cmdlets, structure, detection contract, manifest, log name, driver trust …) → GREEN/RED | `Invoke-PsadtPreflight.ps1` |
76
+ | **5** Pre-flight | 14 checks (encoding, AST parse, v3 cmdlets, structure, detection contract, manifest, log name, driver trust …) → GREEN/RED | `Invoke-PsadtPreflight.ps1` |
77
77
  | **6** SYSTEM test | the whole loop in a throwaway Windows Sandbox, every action as **SYSTEM** like the IME does - no elevation, host untouched. **Binding before any upload** | `Invoke-PsadtSandboxTest.ps1` |
78
78
  | **7** Package | one command → verified `.intunewin`, named after the app | `Invoke-PsadtPackage.ps1` |
79
79
  | **8** Dossier | always, uploaded or not: bilingual self-contained HTML | `New-PsadtReport.ps1` |
@@ -103,7 +103,7 @@ the same app from disagreeing about their own version.
103
103
  - **A dossier is produced every time**, uploaded or not: one self-contained bilingual HTML file with the
104
104
  return-code map, the detection rule, the hooks, the test results - and a ready-to-paste Company-Portal
105
105
  description.
106
- - **757 Pester tests**, including drift guards that fail when the documentation and the code disagree -
106
+ - **921 Pester tests**, including drift guards that fail when the documentation and the code disagree -
107
107
  one of them reads the published landing page and compares its figures against this repository.
108
108
 
109
109
  ## Go deeper
@@ -115,13 +115,13 @@ the same app from disagreeing about their own version.
115
115
  | [`docs/features.md`](docs/features.md) | the complete feature list, package type by package type |
116
116
  | [`docs/setup-and-structure.md`](docs/setup-and-structure.md) | first-run setup, config home, full project structure |
117
117
  | [`SKILL.md`](SKILL.md) | the control plane the agent actually reads |
118
- | [`references/README.md`](references/README.md) | the reference map: phases 0-12 and appendices A-Q |
118
+ | [`references/README.md`](references/README.md) | the reference map: phases 0-12 and appendices A-R |
119
119
  | [`SECURITY.md`](SECURITY.md) | the risk surface and the control covering each part of it |
120
120
 
121
121
  ## Status
122
122
 
123
123
  In active use for the full build → package → test → dossier workflow, with the direct Graph upload
124
- verified against a live tenant. The helper scripts are covered by 757 Pester tests.
124
+ verified against a live tenant. The helper scripts are covered by 921 Pester tests.
125
125
 
126
126
  One open point, honestly: **the driver `pnputil` exit-code semantics are documented, not verified here.**
127
127
  `0` / `259` / `3010` and the two `0xE...` failures come from Microsoft's documentation; confirming them
@@ -170,11 +170,20 @@ installed.
170
170
  **[CHANGELOG.md](CHANGELOG.md)** carries the complete history, every release since 0.1.0, and nothing is
171
171
  ever removed from it.
172
172
 
173
- Latest: **0.44.0 - A GREEN package that would have looped in production.** Google Chrome ships a new MSI
174
- ProductCode with every build and updates itself in place, so the MSI generator's ProductCode-keyed package
175
- passed every gate and would still have been re-installed by Intune every day once GoogleUpdater moved a
176
- device on. `New-MsiPackage.ps1 -SelfUpdatingBinary` now generates a version-floor detection, an install
177
- that skips an equal or newer build, and uninstall/repair by the registered ARP name - verified in the full
178
- sandbox gate on Chrome 154. Every other lesson of that run became a gate too: pre-flight stays RED while
179
- research is unanswered, packing and the sandbox refuse a RED or stale pre-flight, and the upload and the
180
- dossier take the description, logo and detection script from the manifest instead of asking again.
173
+ Latest: **0.47.0 - The supersedence this skill has been wiring may never have been wired.** The upload has
174
+ POSTed a supersedence relationship since 0.8.x, on a route that is reported not to exist, catching the
175
+ failure and printing a yellow line - so a chain that never took looked like a normal run. No test touched
176
+ any of it. The write now uses the `updateRelationships` action the admin center uses, merges onto the
177
+ existing relationships instead of replacing them, and reads the chain back before claiming it. The mode is
178
+ no longer hardcoded to `replace`, which uninstalled the previous version from every device first; `update`
179
+ is the default and the MSI's own Upgrade table decides. Two new scripts make the predecessor's id
180
+ something you can read rather than retype, and Appendix R covers the lifecycle - including that Intune has
181
+ no retire state at all.
182
+
183
+ Previously: **0.46.0 - Sixteen findings, and the two the live run had already proved.** The last sixteen
184
+ findings from the deep analysis. A full run on 0.45.0 had shown two of them for real: the dossier
185
+ existed on disk while the manifest said nothing about it, and the package finished with no logo and no
186
+ warning. The manifest now records what was produced, the three JSON stores are replaced atomically, the
187
+ packaging tool and the four MSAL packages are verified before anything executes, the host re-checks the
188
+ verdict the sandbox hands it, a generator no longer discards a hand-filled package without -Force, and
189
+ an ampersand in a path no longer produces a sandbox that silently starts without its mapped folders.
package/bin/install.mjs CHANGED
@@ -222,8 +222,12 @@ async function main() {
222
222
  // The ref is recorded next to the sha because Update-PsadtSkill.ps1 cannot otherwise tell a
223
223
  // release-pinned installation from one tracking main, and would report a pinned machine as
224
224
  // permanently "behind" every time main moved.
225
- // -Command, not -File: -File passes every argument as a string and -Updates wants a hashtable.
226
- run(psExe, [...psBase, '-Command', `& '${setCfg}' -Updates @{'tooling.skillCommit'='${sha}'; 'tooling.skillRef'='${ref}'}`]);
225
+ // -Command, not -File: -File stringifies every argument and -Updates wants a hashtable. The
226
+ // VALUES travel as environment variables, never interpolated into the source: a ref or a home
227
+ // directory containing an apostrophe would otherwise close the literal and run what follows.
228
+ run(psExe, [...psBase, '-Command',
229
+ "& $env:PSADT_SETCFG -Updates @{'tooling.skillCommit'=$env:PSADT_SHA; 'tooling.skillRef'=$env:PSADT_REF}"],
230
+ { env: { ...process.env, PSADT_SETCFG: setCfg, PSADT_SHA: sha, PSADT_REF: ref } });
227
231
  console.log(` OK recorded commit ${sha.slice(0, 7)} at ref ${ref}`);
228
232
  }
229
233
  } else if (res.status === 404) {
@@ -254,7 +258,8 @@ async function main() {
254
258
  // -Command with Out-Null rather than -File: the doctor also RETURNS its result object, and with inherited
255
259
  // stdout that object gets dumped underneath its own table. Out-Null drops the object; Write-Host output
256
260
  // (the table) is unaffected.
257
- const d = run(psExe, [...psBase, '-Command', `& '${doctor}' -Fix -JsonPath '${jsonPath}' | Out-Null`]);
261
+ const d = run(psExe, [...psBase, '-Command', '& $env:PSADT_DOCTOR -Fix -JsonPath $env:PSADT_JSON | Out-Null'],
262
+ { env: { ...process.env, PSADT_DOCTOR: doctor, PSADT_JSON: jsonPath } });
258
263
 
259
264
  let verdict = null;
260
265
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "psadt-deploy-skill",
3
- "version": "0.44.0",
3
+ "version": "0.47.0",
4
4
  "description": "Installer for the psadt-deploy Claude Code skill: build, test and deploy PSADT v4.x Intune Win32 packages.",
5
5
  "keywords": [
6
6
  "psadt",