@inerrata-corporation/errata 2.0.0-alpha.0 → 2.0.0-dev.21

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.txt CHANGED
@@ -1,56 +1,56 @@
1
- errata - local-first observation engine for coding agents
2
-
3
- Requires Node.js 22 or newer on PATH (https://nodejs.org).
4
-
5
- Install (Windows, no admin rights required):
6
-
7
- .\install.ps1
8
-
9
- This copies errata.mjs + the tree-sitter runtime to %LOCALAPPDATA%\errata
10
- and adds that directory to your user PATH. A small errata.cmd shim runs the
11
- bundle under your system Node.
12
-
13
- It also registers a Scheduled Task (\errata\ai.errata.daemon) that auto-starts
14
- the daemon (`errata dash`) at every logon, launched hidden via a small .vbs so
15
- no console window flashes. uninstall.ps1 removes it. Note: this runs the
16
- installed copy under %LOCALAPPDATA%\errata - re-run install.ps1 after rebuilding
17
- to keep the autostarted daemon current.
18
-
19
- macOS / Linux:
20
-
21
- errata.mjs carries a `#!/usr/bin/env node` shebang. Put the dist/ folder
22
- somewhere stable, then symlink the bundle onto your PATH:
23
-
24
- chmod +x errata.mjs
25
- ln -s "$PWD/errata.mjs" ~/.local/bin/errata
26
-
27
- The resources/wasm/ folder must stay next to errata.mjs.
28
-
29
- Use:
30
-
31
- cd C:\path\to\your\project
32
- errata init # auto-detects profile + installs harness hooks
33
- errata start # observe this repo
34
- errata status # verify the whole chain (daemon, cloud, consent)
35
-
36
- Model caveat (Claude Code + Claude Fable 5): the harness treats Fable 5's
37
- mid-turn assistant text (written between tool calls) as ephemeral - it reaches
38
- neither the session transcript nor the MessageDisplay hook, so inline tags
39
- written mid-turn are lost on every capture channel. errata's agent instruction
40
- tells the agent to restate mid-turn tags in its final message (which always
41
- survives), so expect reduced mid-turn capture on Fable sessions; Opus/Sonnet
42
- sessions are fully captured. (Verified with a 3-model matrix, 2026-07-02.)
43
-
44
- Open the dashboard: http://127.0.0.1:7891
45
-
46
- Point at a cloud (defaults to the public instance):
47
-
48
- errata init --cloud https://your-instance --token <api-key>
49
- errata login # or browser device-code flow
50
-
51
- Per-workspace state lives at .errata/ inside each project root and is
52
- preserved on uninstall - delete manually if you want it gone.
53
-
54
- Uninstall (Windows):
55
-
56
- .\uninstall.ps1
1
+ errata - local-first observation engine for coding agents
2
+
3
+ Requires Node.js 22 or newer on PATH (https://nodejs.org).
4
+
5
+ Install (Windows, no admin rights required):
6
+
7
+ .\install.ps1
8
+
9
+ This copies errata.mjs + the tree-sitter runtime to %LOCALAPPDATA%\errata
10
+ and adds that directory to your user PATH. A small errata.cmd shim runs the
11
+ bundle under your system Node.
12
+
13
+ It also registers a Scheduled Task (\errata\ai.errata.daemon) that auto-starts
14
+ the daemon (`errata dash`) at every logon, launched hidden via a small .vbs so
15
+ no console window flashes. uninstall.ps1 removes it. Note: this runs the
16
+ installed copy under %LOCALAPPDATA%\errata - re-run install.ps1 after rebuilding
17
+ to keep the autostarted daemon current.
18
+
19
+ macOS / Linux:
20
+
21
+ errata.mjs carries a `#!/usr/bin/env node` shebang. Put the dist/ folder
22
+ somewhere stable, then symlink the bundle onto your PATH:
23
+
24
+ chmod +x errata.mjs
25
+ ln -s "$PWD/errata.mjs" ~/.local/bin/errata
26
+
27
+ The resources/wasm/ folder must stay next to errata.mjs.
28
+
29
+ Use:
30
+
31
+ cd C:\path\to\your\project
32
+ errata init # auto-detects profile + installs harness hooks
33
+ errata start # observe this repo
34
+ errata status # verify the whole chain (daemon, cloud, consent)
35
+
36
+ Model caveat (Claude Code + Claude Fable 5): the harness treats Fable 5's
37
+ mid-turn assistant text (written between tool calls) as ephemeral - it reaches
38
+ neither the session transcript nor the MessageDisplay hook, so inline tags
39
+ written mid-turn are lost on every capture channel. errata's agent instruction
40
+ tells the agent to restate mid-turn tags in its final message (which always
41
+ survives), so expect reduced mid-turn capture on Fable sessions; Opus/Sonnet
42
+ sessions are fully captured. (Verified with a 3-model matrix, 2026-07-02.)
43
+
44
+ Open the dashboard: http://127.0.0.1:7891
45
+
46
+ Point at a cloud (defaults to the public instance):
47
+
48
+ errata init --cloud https://your-instance --token <api-key>
49
+ errata login # or browser device-code flow
50
+
51
+ Per-workspace state lives at .errata/ inside each project root and is
52
+ preserved on uninstall - delete manually if you want it gone.
53
+
54
+ Uninstall (Windows):
55
+
56
+ .\uninstall.ps1
package/errata.mjs CHANGED
@@ -39472,8 +39472,11 @@ function fixRationaleBefore(sentence, idx) {
39472
39472
  function parseInlineTags(text) {
39473
39473
  const out2 = [];
39474
39474
  const deFenced = text.replace(/```[\s\S]*?```/g, " ");
39475
+ let seqNo = -1;
39475
39476
  for (const raw2 of deFenced.split(/(?<=[.!?])\s+|\n+/)) {
39477
+ seqNo++;
39476
39478
  if (raw2.length > 600) continue;
39479
+ const seqStart = out2.length;
39477
39480
  const sentence = raw2.replace(
39478
39481
  /`[^`]*`/g,
39479
39482
  (m) => /\[[!?]|\((?:fix|cause|constraint):|\(\[/.test(m) ? " " : m
@@ -39559,6 +39562,7 @@ function parseInlineTags(text) {
39559
39562
  out2.push({ kind: "constraint", statement, sentence: sfield });
39560
39563
  }
39561
39564
  }
39565
+ for (let i2 = seqStart; i2 < out2.length; i2++) out2[i2].seq = seqNo;
39562
39566
  }
39563
39567
  return out2;
39564
39568
  }
@@ -39670,7 +39674,18 @@ function harvestInlineTags(store, text, opts) {
39670
39674
  const mintPriors = opts.mintPriors ?? true;
39671
39675
  const touched = opts.sessionTouchedIds ?? /* @__PURE__ */ new Set();
39672
39676
  const plan = { priorEdges: 0, problems: [], fixes: [], triages: [], unresolvedFixes: [] };
39673
- for (const tag of parseInlineTags(text)) {
39677
+ const tags = parseInlineTags(text);
39678
+ const symptomSeqs = tags.filter((t) => (t.kind === "problem" || t.kind === "todo" || t.kind === "constraint") && t.statement).map((t) => ({ seq: t.seq ?? -1, statement: t.statement })).sort((a, b) => a.seq - b.seq);
39679
+ const nearestSymptom = (seq) => {
39680
+ if (seq == null) return void 0;
39681
+ let best;
39682
+ for (const s of symptomSeqs) {
39683
+ if (s.seq <= seq) best = s.statement;
39684
+ else break;
39685
+ }
39686
+ return best;
39687
+ };
39688
+ for (const tag of tags) {
39674
39689
  if (tag.kind === "problem" || tag.kind === "todo") {
39675
39690
  plan.problems.push({
39676
39691
  statement: tag.statement,
@@ -39688,13 +39703,14 @@ function harvestInlineTags(store, text, opts) {
39688
39703
  plan.fixes.push({ inScope: true, fixNote: tag.fixRationale });
39689
39704
  }
39690
39705
  } else if (tag.kind === "triage") {
39706
+ const symptomStatement = nearestSymptom(tag.seq);
39691
39707
  if (tag.handle) {
39692
39708
  const causeId = resolveHandle(store, tag.handle, opts.handleMap);
39693
39709
  const node2 = causeId ? store.getNode(causeId) : null;
39694
- if (node2) plan.triages.push({ causeId: node2.id, causeDescription: node2.description });
39710
+ if (node2) plan.triages.push({ causeId: node2.id, causeDescription: node2.description, ...symptomStatement ? { symptomStatement } : {} });
39695
39711
  } else if (tag.causeText) {
39696
39712
  const causeId = `dcause_${digest({ statement: tag.causeText })}`.slice(0, 56);
39697
- plan.triages.push({ causeId, causeDescription: tag.causeText });
39713
+ plan.triages.push({ causeId, causeDescription: tag.causeText, ...symptomStatement ? { symptomStatement } : {} });
39698
39714
  }
39699
39715
  } else if (mintPriors && source) {
39700
39716
  const targetId = resolveHandle(store, tag.handle, opts.handleMap);
@@ -40951,7 +40967,7 @@ function maybeFlushDigests() {
40951
40967
  }
40952
40968
 
40953
40969
  // src/engine.ts
40954
- var DAEMON_VERSION = true ? "2.0.0-alpha.0" : "2.0.0-alpha.0";
40970
+ var DAEMON_VERSION = true ? "2.0.0-dev.21" : "2.0.0-alpha.0";
40955
40971
  var IGNORED_PATH = /[\\/](?:\.git|node_modules|\.errata|\.claude|\.codex|\.cursor|\.turbo|\.next|dist|coverage|test-results|playwright-report|__pycache__)(?:[\\/]|$)/;
40956
40972
  var IGNORED_NOISE = /castalia\.db|eventlog\.sqlite|turn-cursors/;
40957
40973
  var GIT_OP_MUTE_MS = 4e3;
@@ -41542,27 +41558,29 @@ function createWorkspaceEngine(opts) {
41542
41558
  }
41543
41559
  }
41544
41560
  if (opts.sharedStore && plan.triages.length > 0) {
41545
- const symptomId = sessionLastProblem.get(sessionId);
41546
- const symptom = symptomId ? store.getNode(symptomId) : void 0;
41547
- if (symptom) {
41548
- for (const tr of plan.triages) {
41549
- if (tr.causeId === symptomId) continue;
41550
- try {
41551
- recordTriageObservation(
41552
- opts.sharedStore,
41553
- {
41554
- presentingStatement: symptom.description,
41555
- causeId: tr.causeId,
41556
- ...tr.causeDescription ? { causeDescription: tr.causeDescription } : {},
41557
- context: { stack: profile.stack, domain: profile.domains[0] },
41558
- contributor: sessionId
41559
- },
41560
- t
41561
- );
41562
- triaged++;
41563
- } catch (err2) {
41564
- console.warn("[errata] inline triage route failed:", err2);
41565
- }
41561
+ const fallbackId = sessionLastProblem.get(sessionId);
41562
+ const fallbackStatement = fallbackId ? store.getNode(fallbackId)?.description : void 0;
41563
+ for (const tr of plan.triages) {
41564
+ const presentingStatement = tr.symptomStatement ?? fallbackStatement;
41565
+ if (!presentingStatement) continue;
41566
+ const presentingId = designProblemId(presentingStatement);
41567
+ if (tr.causeId === presentingId) continue;
41568
+ try {
41569
+ recordTriageObservation(
41570
+ opts.sharedStore,
41571
+ {
41572
+ presentingStatement,
41573
+ presentingId,
41574
+ causeId: tr.causeId,
41575
+ ...tr.causeDescription ? { causeDescription: tr.causeDescription } : {},
41576
+ context: { stack: profile.stack, domain: profile.domains[0] },
41577
+ contributor: sessionId
41578
+ },
41579
+ t
41580
+ );
41581
+ triaged++;
41582
+ } catch (err2) {
41583
+ console.warn("[errata] inline triage route failed:", err2);
41566
41584
  }
41567
41585
  }
41568
41586
  }
package/install.ps1 CHANGED
@@ -1,90 +1,90 @@
1
- # errata Windows installer / patcher (Node-bundle distribution).
2
- # Idempotent: re-running upgrades an existing install in place.
3
- #
4
- # Unlike the old SEA build (a 90 MB self-contained errata.exe), this ships the
5
- # CLI as a single bundled errata.mjs run under the system Node — so Node 22+ must
6
- # be on PATH. Everything else (tree-sitter WASM) rides along under resources/.
7
-
8
- $ErrorActionPreference = "Stop"
9
- $ScriptRoot = $PSScriptRoot
10
- if (-not $ScriptRoot) { $ScriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Path }
11
-
12
- # errata runs on the system Node — fail loudly if it's missing rather than after install.
13
- $node = Get-Command node -ErrorAction SilentlyContinue
14
- if (-not $node) {
15
- Write-Host "[X] Node.js not found on PATH. Install Node 22+ from https://nodejs.org and re-run."
16
- exit 1
17
- }
18
- $nodeMajor = (& node -e "process.stdout.write(String(process.versions.node.split('.')[0]))")
19
- if ([int]$nodeMajor -lt 22) {
20
- Write-Host "[X] Node $nodeMajor found, but errata needs Node 22+. Upgrade and re-run."
21
- exit 1
22
- }
23
-
24
- $Target = Join-Path $env:LOCALAPPDATA "errata"
25
- $IsPatch = Test-Path (Join-Path $Target "errata.mjs")
26
-
27
- if ($IsPatch) {
28
- Write-Host "patching existing errata install at $Target"
29
- } else {
30
- Write-Host "installing errata to $Target (Node $nodeMajor)"
31
- }
32
-
33
- if (-not (Test-Path $Target)) {
34
- New-Item -ItemType Directory -Path $Target | Out-Null
35
- }
36
- Copy-Item -Path (Join-Path $ScriptRoot "errata.mjs") -Destination $Target -Force
37
- Copy-Item -Path (Join-Path $ScriptRoot "errata.cmd") -Destination $Target -Force
38
- $ResSrc = Join-Path $ScriptRoot "resources"
39
- $ResDst = Join-Path $Target "resources"
40
- if (Test-Path $ResDst) { Remove-Item $ResDst -Recurse -Force }
41
- Copy-Item -Path $ResSrc -Destination $Target -Recurse -Force
42
-
43
- $UserPath = [Environment]::GetEnvironmentVariable("Path", "User")
44
- $PathParts = if ($UserPath) { $UserPath.Split(";") } else { @() }
45
- if ($PathParts -notcontains $Target) {
46
- $NewPath = if ($UserPath) { "$UserPath;$Target" } else { $Target }
47
- [Environment]::SetEnvironmentVariable("Path", $NewPath, "User")
48
- Write-Host "added $Target to user PATH"
49
- Write-Host " (open a new terminal for PATH changes to take effect)"
50
- } else {
51
- Write-Host "PATH already contains $Target"
52
- }
53
-
54
- # Auto-start the daemon at logon via a Scheduled Task. We launch through a hidden
55
- # .vbs shim because node.exe is a console app — running it from the task directly
56
- # flashes a window every logon; WScript's Run(..., 0, False) starts it windowless.
57
- # Task name/path mirror uninstall.ps1 (\errata\ai.errata.daemon) so the two stay
58
- # symmetric. Best-effort: a failure here must not fail the install.
59
- $VbsTemplate = @'
60
- ' errata daemon autostart launcher (written by install.ps1) - runs `errata dash` fully hidden.
61
- Set sh = CreateObject("WScript.Shell")
62
- sh.CurrentDirectory = "__CWD__"
63
- sh.Run """__NODE__"" ""__MJS__"" dash", 0, False
64
- '@
65
- try {
66
- $Launcher = Join-Path $Target "errata-autostart.vbs"
67
- $Vbs = $VbsTemplate.Replace("__CWD__", $env:USERPROFILE).Replace("__NODE__", $node.Source).Replace("__MJS__", (Join-Path $Target "errata.mjs"))
68
- Set-Content -Path $Launcher -Value $Vbs -Encoding ASCII
69
-
70
- $action = New-ScheduledTaskAction -Execute "wscript.exe" -Argument ('"{0}"' -f $Launcher)
71
- $trigger = New-ScheduledTaskTrigger -AtLogOn -User $env:USERNAME
72
- $settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable -ExecutionTimeLimit (New-TimeSpan -Seconds 0) -RestartCount 3 -RestartInterval (New-TimeSpan -Minutes 1)
73
- $principal = New-ScheduledTaskPrincipal -UserId $env:USERNAME -LogonType Interactive -RunLevel Limited
74
- Register-ScheduledTask -TaskName "ai.errata.daemon" -TaskPath "\errata\" -Action $action -Trigger $trigger -Settings $settings -Principal $principal -Description "Auto-start the errata dash daemon at logon." -Force | Out-Null
75
- Write-Host "registered autostart task \errata\ai.errata.daemon (starts at logon)"
76
- } catch {
77
- Write-Host "[!] could not register autostart task: $($_.Exception.Message)"
78
- Write-Host " (install still succeeded - start the daemon manually with 'errata dash')"
79
- }
80
-
81
- Write-Host ""
82
- if ($IsPatch) { Write-Host "[OK] errata patched." } else { Write-Host "[OK] errata installed." }
83
- Write-Host ""
84
- Write-Host "Next steps:"
85
- Write-Host " 1. Open a new terminal so PATH refreshes."
86
- Write-Host " 2. cd into the workspace you want to observe."
87
- Write-Host " 3. errata init"
88
- Write-Host " 4. errata start (or 'errata dash' to watch all projects)"
89
- Write-Host ""
90
- Write-Host "The daemon will also auto-start at every logon from now on."
1
+ # errata Windows installer / patcher (Node-bundle distribution).
2
+ # Idempotent: re-running upgrades an existing install in place.
3
+ #
4
+ # Unlike the old SEA build (a 90 MB self-contained errata.exe), this ships the
5
+ # CLI as a single bundled errata.mjs run under the system Node — so Node 22+ must
6
+ # be on PATH. Everything else (tree-sitter WASM) rides along under resources/.
7
+
8
+ $ErrorActionPreference = "Stop"
9
+ $ScriptRoot = $PSScriptRoot
10
+ if (-not $ScriptRoot) { $ScriptRoot = Split-Path -Parent $MyInvocation.MyCommand.Path }
11
+
12
+ # errata runs on the system Node — fail loudly if it's missing rather than after install.
13
+ $node = Get-Command node -ErrorAction SilentlyContinue
14
+ if (-not $node) {
15
+ Write-Host "[X] Node.js not found on PATH. Install Node 22+ from https://nodejs.org and re-run."
16
+ exit 1
17
+ }
18
+ $nodeMajor = (& node -e "process.stdout.write(String(process.versions.node.split('.')[0]))")
19
+ if ([int]$nodeMajor -lt 22) {
20
+ Write-Host "[X] Node $nodeMajor found, but errata needs Node 22+. Upgrade and re-run."
21
+ exit 1
22
+ }
23
+
24
+ $Target = Join-Path $env:LOCALAPPDATA "errata"
25
+ $IsPatch = Test-Path (Join-Path $Target "errata.mjs")
26
+
27
+ if ($IsPatch) {
28
+ Write-Host "patching existing errata install at $Target"
29
+ } else {
30
+ Write-Host "installing errata to $Target (Node $nodeMajor)"
31
+ }
32
+
33
+ if (-not (Test-Path $Target)) {
34
+ New-Item -ItemType Directory -Path $Target | Out-Null
35
+ }
36
+ Copy-Item -Path (Join-Path $ScriptRoot "errata.mjs") -Destination $Target -Force
37
+ Copy-Item -Path (Join-Path $ScriptRoot "errata.cmd") -Destination $Target -Force
38
+ $ResSrc = Join-Path $ScriptRoot "resources"
39
+ $ResDst = Join-Path $Target "resources"
40
+ if (Test-Path $ResDst) { Remove-Item $ResDst -Recurse -Force }
41
+ Copy-Item -Path $ResSrc -Destination $Target -Recurse -Force
42
+
43
+ $UserPath = [Environment]::GetEnvironmentVariable("Path", "User")
44
+ $PathParts = if ($UserPath) { $UserPath.Split(";") } else { @() }
45
+ if ($PathParts -notcontains $Target) {
46
+ $NewPath = if ($UserPath) { "$UserPath;$Target" } else { $Target }
47
+ [Environment]::SetEnvironmentVariable("Path", $NewPath, "User")
48
+ Write-Host "added $Target to user PATH"
49
+ Write-Host " (open a new terminal for PATH changes to take effect)"
50
+ } else {
51
+ Write-Host "PATH already contains $Target"
52
+ }
53
+
54
+ # Auto-start the daemon at logon via a Scheduled Task. We launch through a hidden
55
+ # .vbs shim because node.exe is a console app — running it from the task directly
56
+ # flashes a window every logon; WScript's Run(..., 0, False) starts it windowless.
57
+ # Task name/path mirror uninstall.ps1 (\errata\ai.errata.daemon) so the two stay
58
+ # symmetric. Best-effort: a failure here must not fail the install.
59
+ $VbsTemplate = @'
60
+ ' errata daemon autostart launcher (written by install.ps1) - runs `errata dash` fully hidden.
61
+ Set sh = CreateObject("WScript.Shell")
62
+ sh.CurrentDirectory = "__CWD__"
63
+ sh.Run """__NODE__"" ""__MJS__"" dash", 0, False
64
+ '@
65
+ try {
66
+ $Launcher = Join-Path $Target "errata-autostart.vbs"
67
+ $Vbs = $VbsTemplate.Replace("__CWD__", $env:USERPROFILE).Replace("__NODE__", $node.Source).Replace("__MJS__", (Join-Path $Target "errata.mjs"))
68
+ Set-Content -Path $Launcher -Value $Vbs -Encoding ASCII
69
+
70
+ $action = New-ScheduledTaskAction -Execute "wscript.exe" -Argument ('"{0}"' -f $Launcher)
71
+ $trigger = New-ScheduledTaskTrigger -AtLogOn -User $env:USERNAME
72
+ $settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable -ExecutionTimeLimit (New-TimeSpan -Seconds 0) -RestartCount 3 -RestartInterval (New-TimeSpan -Minutes 1)
73
+ $principal = New-ScheduledTaskPrincipal -UserId $env:USERNAME -LogonType Interactive -RunLevel Limited
74
+ Register-ScheduledTask -TaskName "ai.errata.daemon" -TaskPath "\errata\" -Action $action -Trigger $trigger -Settings $settings -Principal $principal -Description "Auto-start the errata dash daemon at logon." -Force | Out-Null
75
+ Write-Host "registered autostart task \errata\ai.errata.daemon (starts at logon)"
76
+ } catch {
77
+ Write-Host "[!] could not register autostart task: $($_.Exception.Message)"
78
+ Write-Host " (install still succeeded - start the daemon manually with 'errata dash')"
79
+ }
80
+
81
+ Write-Host ""
82
+ if ($IsPatch) { Write-Host "[OK] errata patched." } else { Write-Host "[OK] errata installed." }
83
+ Write-Host ""
84
+ Write-Host "Next steps:"
85
+ Write-Host " 1. Open a new terminal so PATH refreshes."
86
+ Write-Host " 2. cd into the workspace you want to observe."
87
+ Write-Host " 3. errata init"
88
+ Write-Host " 4. errata start (or 'errata dash' to watch all projects)"
89
+ Write-Host ""
90
+ Write-Host "The daemon will also auto-start at every logon from now on."
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inerrata-corporation/errata",
3
- "version": "2.0.0-alpha.0",
3
+ "version": "2.0.0-dev.21",
4
4
  "description": "errata - local-first observation engine for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
package/uninstall.ps1 CHANGED
@@ -1,29 +1,29 @@
1
- # errata uninstaller.
2
- $ErrorActionPreference = "Stop"
3
- $Target = Join-Path $env:LOCALAPPDATA "errata"
4
-
5
- if (-not (Test-Path $Target)) {
6
- Write-Host "errata is not installed at $Target."
7
- exit 0
8
- }
9
-
10
- Write-Host "removing $Target"
11
- Remove-Item -Path $Target -Recurse -Force
12
-
13
- $UserPath = [Environment]::GetEnvironmentVariable("Path", "User")
14
- if ($UserPath) {
15
- $PathParts = $UserPath.Split(";") | Where-Object { $_ -ne $Target }
16
- $NewPath = ($PathParts -join ";").Trim(";")
17
- [Environment]::SetEnvironmentVariable("Path", $NewPath, "User")
18
- Write-Host "removed $Target from user PATH"
19
- }
20
-
21
- $Existing = Get-ScheduledTask -TaskName "ai.errata.daemon" -TaskPath "\errata\" -ErrorAction SilentlyContinue
22
- if ($Existing) {
23
- Unregister-ScheduledTask -TaskName "ai.errata.daemon" -TaskPath "\errata\" -Confirm:$false
24
- Write-Host "removed scheduled task errata\ai.errata.daemon"
25
- }
26
-
27
- Write-Host ""
28
- Write-Host "[OK] errata uninstalled."
29
- Write-Host "Per-workspace .errata/ folders are left in place - delete them manually if desired."
1
+ # errata uninstaller.
2
+ $ErrorActionPreference = "Stop"
3
+ $Target = Join-Path $env:LOCALAPPDATA "errata"
4
+
5
+ if (-not (Test-Path $Target)) {
6
+ Write-Host "errata is not installed at $Target."
7
+ exit 0
8
+ }
9
+
10
+ Write-Host "removing $Target"
11
+ Remove-Item -Path $Target -Recurse -Force
12
+
13
+ $UserPath = [Environment]::GetEnvironmentVariable("Path", "User")
14
+ if ($UserPath) {
15
+ $PathParts = $UserPath.Split(";") | Where-Object { $_ -ne $Target }
16
+ $NewPath = ($PathParts -join ";").Trim(";")
17
+ [Environment]::SetEnvironmentVariable("Path", $NewPath, "User")
18
+ Write-Host "removed $Target from user PATH"
19
+ }
20
+
21
+ $Existing = Get-ScheduledTask -TaskName "ai.errata.daemon" -TaskPath "\errata\" -ErrorAction SilentlyContinue
22
+ if ($Existing) {
23
+ Unregister-ScheduledTask -TaskName "ai.errata.daemon" -TaskPath "\errata\" -Confirm:$false
24
+ Write-Host "removed scheduled task errata\ai.errata.daemon"
25
+ }
26
+
27
+ Write-Host ""
28
+ Write-Host "[OK] errata uninstalled."
29
+ Write-Host "Per-workspace .errata/ folders are left in place - delete them manually if desired."