@caddis/cli 0.4.22 → 0.4.24

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.
Files changed (35) hide show
  1. package/bundles/antigravity-plugin/plugin.json +1 -1
  2. package/bundles/antigravity-plugin/skills/_registry.md +1 -1
  3. package/bundles/antigravity-plugin/skills/port-to-github/SKILL.md +64 -3
  4. package/bundles/antigravity-plugin/skills/port-to-github/scripts/Get-PortSource.ps1 +30 -2
  5. package/bundles/antigravity-plugin/skills/port-to-github/scripts/Invoke-PortHistoryClean.ps1 +123 -0
  6. package/bundles/antigravity-plugin/skills/port-to-github/scripts/New-PortRuntimeManifest.ps1 +258 -0
  7. package/bundles/antigravity-plugin/skills/port-to-github/scripts/Publish-PortToGitHub.ps1 +20 -1
  8. package/bundles/antigravity-plugin/skills/port-to-github/scripts/Test-PortContentPolicy.ps1 +218 -0
  9. package/bundles/antigravity-plugin-extras/plugin.json +1 -1
  10. package/bundles/antigravity-plugin-extras/skills/_registry.md +1 -0
  11. package/bundles/antigravity-plugin-extras/skills/adopt-app/SKILL.md +174 -0
  12. package/bundles/antigravity-plugin-extras/skills/adopt-app/profiles/_template/profile.json +55 -0
  13. package/bundles/antigravity-plugin-extras/skills/adopt-app/profiles/batch-job/profile.json +68 -0
  14. package/bundles/antigravity-plugin-extras/skills/adopt-app/profiles/dotnet-service/profile.json +67 -0
  15. package/bundles/antigravity-plugin-extras/skills/adopt-app/profiles/java-service/profile.json +62 -0
  16. package/bundles/antigravity-plugin-extras/skills/adopt-app/profiles/node-service/profile.json +66 -0
  17. package/bundles/antigravity-plugin-extras/skills/adopt-app/profiles/php-db/profile.json +75 -0
  18. package/bundles/antigravity-plugin-extras/skills/adopt-app/profiles/python-web/profile.json +73 -0
  19. package/bundles/antigravity-plugin-extras/skills/adopt-app/profiles/static-site/profile.json +87 -0
  20. package/bundles/antigravity-plugin-extras/skills/adopt-app/references/config.example.json +18 -0
  21. package/bundles/antigravity-plugin-extras/skills/adopt-app/references/profile-contract.md +207 -0
  22. package/bundles/antigravity-plugin-extras/skills/adopt-app/references/standard.md +304 -0
  23. package/bundles/antigravity-plugin-extras/skills/adopt-app/scripts/AdoptCommon.ps1 +812 -0
  24. package/bundles/antigravity-plugin-extras/skills/adopt-app/scripts/Get-AppInventory.ps1 +236 -0
  25. package/bundles/antigravity-plugin-extras/skills/adopt-app/scripts/New-AdoptionPlan.ps1 +311 -0
  26. package/bundles/antigravity-plugin-extras/skills/adopt-app/scripts/Resolve-AppProfile.ps1 +246 -0
  27. package/bundles/antigravity-plugin-extras/skills/adopt-app/scripts/Test-AppConformance.ps1 +343 -0
  28. package/bundles/codex/.codex/skills/devops/port-to-github/SKILL.md +64 -3
  29. package/bundles/codex/.codex/skills/devops/port-to-github/scripts/Get-PortSource.ps1 +30 -2
  30. package/bundles/codex/.codex/skills/devops/port-to-github/scripts/Invoke-PortHistoryClean.ps1 +123 -0
  31. package/bundles/codex/.codex/skills/devops/port-to-github/scripts/New-PortRuntimeManifest.ps1 +258 -0
  32. package/bundles/codex/.codex/skills/devops/port-to-github/scripts/Publish-PortToGitHub.ps1 +20 -1
  33. package/bundles/codex/.codex/skills/devops/port-to-github/scripts/Test-PortContentPolicy.ps1 +218 -0
  34. package/bundles/manifest.json +3 -3
  35. package/package.json +1 -1
@@ -0,0 +1,218 @@
1
+ <#
2
+ .SYNOPSIS
3
+ Check a staged repository against the source-only content policy, over the tips AND all history.
4
+
5
+ .DESCRIPTION
6
+ The policy: a repository holds application code, configuration and templates, migration
7
+ SCRIPTS, tests, and the scripts/manifests that rebuild the environment. It does NOT hold:
8
+
9
+ runtime a runtime or server distribution (MariaDB, PHP, JDK, Node, Python, Apache...)
10
+ binary compiled or packaged files (.exe .dll .so .jar .msi, archives)
11
+ db-data database data files (ibdata1, *.ibd, *.frm, *.mdf, SQLite files, dumps)
12
+ data-export data files above the size threshold (.csv .xlsx .json .xml .sql ...), or any
13
+ data file under a backups/dumps/exports folder
14
+ dependency installed dependencies (node_modules, vendor, .venv, site-packages)
15
+ backup editor and copy backups (*.bak, *.orig, *.old, *~)
16
+
17
+ Large files that match no rule are reported as 'large-review' (a decision, not a violation).
18
+
19
+ .gitignore does not remove a file that was committed before it: every excluded path is
20
+ checked in ALL history, not only in the current files.
21
+
22
+ Reads <staging>\<Name>\mirror.git. Changes nothing. Writes content-policy.json next to it.
23
+ Exit 0: compliant. Exit 1: at least one excluded path exists somewhere in history.
24
+
25
+ Project overrides (optional) in the config file, key "contentPolicy":
26
+ { "keep": ["regex", ...], "exclude": ["regex", ...], "dataThresholdMB": 5, "largeMB": 10 }
27
+ Regexes match the repository path (forward slashes).
28
+ #>
29
+ [CmdletBinding()]
30
+ param(
31
+ [Parameter(Mandatory)][string]$Name,
32
+ [string]$StagingRoot,
33
+ [string]$ConfigPath,
34
+ [double]$DataThresholdMB,
35
+ [double]$LargeMB,
36
+ # Print every finding, not only the per-folder summary.
37
+ [switch]$Detail
38
+ )
39
+
40
+ $ErrorActionPreference = 'Stop'
41
+ . (Join-Path $PSScriptRoot 'PortCommon.ps1')
42
+
43
+ $config = Get-PortConfig $ConfigPath
44
+ $stage = Join-Path (Get-PortStagingRoot $config $StagingRoot) $Name
45
+ $mirror = Join-Path $stage 'mirror.git'
46
+ if (-not (Test-Path -LiteralPath $mirror)) { throw "No staged mirror at $mirror. Run Get-PortSource.ps1 first." }
47
+ $manifest = Get-Content -LiteralPath (Join-Path $stage 'manifest.json') -Raw | ConvertFrom-Json
48
+ $branch = $manifest.defaultBranch
49
+
50
+ $policy = Get-PortConfigValue $config 'contentPolicy' $null
51
+ $keepRx = @(); $extraExcludeRx = @()
52
+ if ($policy) {
53
+ if ($policy.PSObject.Properties.Name -contains 'keep') { $keepRx = @($policy.keep) }
54
+ if ($policy.PSObject.Properties.Name -contains 'exclude') { $extraExcludeRx = @($policy.exclude) }
55
+ if (-not $DataThresholdMB -and $policy.PSObject.Properties.Name -contains 'dataThresholdMB') { $DataThresholdMB = [double]$policy.dataThresholdMB }
56
+ if (-not $LargeMB -and $policy.PSObject.Properties.Name -contains 'largeMB') { $LargeMB = [double]$policy.largeMB }
57
+ }
58
+ if (-not $DataThresholdMB) { $DataThresholdMB = 5 }
59
+ if (-not $LargeMB) { $LargeMB = 10 }
60
+ $dataBytes = [int64]($DataThresholdMB * 1MB)
61
+ $largeBytes = [int64]($LargeMB * 1MB)
62
+
63
+ # A runtime folder is the runtime's NAME, optionally followed by a version or platform tag
64
+ # (php-8.3.33, jdk-17.0.2, node-v20.11.0-win-x64, apache24). Not any folder that merely STARTS
65
+ # with one: redis-migrations/ or apache-poi-wrapper/ are source.
66
+ $ver = '([-_ ]?v?\d[\w.]*(-(win|linux|x64|x86|amd64|arm64)[\w.-]*)?)?'
67
+ $runtimeDirRx = "(?i)^(mariadb|mysql|mysql-server|php|jdk|jre|openjdk|java|python|python-embed|nodejs|node|apache|httpd|nginx|tomcat|apache-tomcat|redis|postgres|postgresql|pgsql|erlang|ruby|dotnet|go)$ver$"
68
+ $runtimeBinRx = '(?i)^(mariadbd|mysqld|mariadb|mysql|php|php-cgi|node|python|pythonw|java|javaw|httpd|nginx|redis-server|postgres|pg_ctl|erl|ruby|dotnet)\.exe$'
69
+ $dependencyDirRx = '(?i)^(node_modules|vendor|\.venv|venv|site-packages|bower_components|\.yarn|jspm_packages)$'
70
+ $binaryExtRx = '(?i)\.(exe|dll|so|dylib|msi|msix|bin|iso|img|jar|war|ear|class|pyc|pdb|lib|a|o|obj|zip|7z|tar|gz|tgz|rar|bz2|xz|cab|nupkg|whl|deb|rpm)$'
71
+ $dbDataRx = '(?i)(^|/)(ibdata\d*|ib_logfile\d*|ib_buffer_pool|aria_log[\w.]*|undo\d+)$|\.(ibd|frm|myd|myi|mdf|ldf|ndf|sqlite3?|db3|dmp)$'
72
+ $backupRx = '(?i)(\.(bak|orig|old|swp)|~)$'
73
+ $dataExtRx = '(?i)\.(csv|tsv|xlsx|xlsm|xlsb|xls|ods|parquet|avro|orc|jsonl|ndjson|json|xml|sql|dat|txt|log)$'
74
+ $dataDirRx = '(?i)^(backups?|dumps?|exports?|snapshots?|data-?dumps?)$'
75
+
76
+ function Get-Category([string]$Path, [int64]$Bytes) {
77
+ foreach ($rx in $keepRx) { if ($Path -match $rx) { return $null } }
78
+ foreach ($rx in $extraExcludeRx) { if ($Path -match $rx) { return 'project-exclude' } }
79
+ $parts = $Path -split '/'
80
+ $dirs = if ($parts.Count -gt 1) { $parts[0..($parts.Count - 2)] } else { @() }
81
+ $leaf = $parts[-1]
82
+ foreach ($d in $dirs) { if ($d -match $runtimeDirRx) { return 'runtime' } }
83
+ if ($leaf -match $runtimeBinRx) { return 'runtime' }
84
+ foreach ($d in $dirs) { if ($d -match $dependencyDirRx) { return 'dependency' } }
85
+ if ($Path -match $dbDataRx) { return 'db-data' }
86
+ if ($leaf -match $backupRx) { return 'backup' }
87
+ if ($leaf -match $binaryExtRx) { return 'binary' }
88
+ if ($leaf -match $dataExtRx) {
89
+ # Under a backups/dumps folder any data file is excluded, but a plain note (.txt/.md) is not data.
90
+ if ($leaf -notmatch '(?i)\.(txt|md)$') { foreach ($d in $dirs) { if ($d -match $dataDirRx) { return 'data-export' } } }
91
+ # Migration SCRIPTS stay by policy. A large .sql under migration(s)/ may be a script or a
92
+ # data load, so it is a decision, not an automatic exclusion. Data FILES there (csv, json,
93
+ # xlsx) are still data.
94
+ if ($leaf -match '(?i)\.sql$' -and ($dirs | Where-Object { $_ -match '(?i)^migrations?$' })) {
95
+ if ($Bytes -ge $largeBytes -or $Bytes -ge $dataBytes) { return 'large-review' }
96
+ return $null
97
+ }
98
+ if ($Bytes -ge $dataBytes) { return 'data-export' }
99
+ }
100
+ if ($Bytes -ge $largeBytes) { return 'large-review' }
101
+ return $null
102
+ }
103
+
104
+ function MGit([string[]]$a) { Invoke-PortGit (@('-C', $mirror) + $a) }
105
+
106
+ # ---- every blob in history, with every path it ever had ----------------------------------
107
+ Write-PortStep 'Reading every path and blob in history'
108
+ $pathsBySha = @{}
109
+ $submodules = New-Object System.Collections.Generic.HashSet[string]
110
+ function Add-PathForSha([string]$sha, [string]$p) {
111
+ if (-not $pathsBySha.ContainsKey($sha)) { $pathsBySha[$sha] = New-Object System.Collections.Generic.HashSet[string] }
112
+ [void]$pathsBySha[$sha].Add($p)
113
+ }
114
+ # EVERY path a blob was ever written to. rev-list --objects names each blob only ONCE, by the
115
+ # first path it meets, so identical content at a second path was invisible (found by the
116
+ # dogfood: a 3-byte test image at two paths survived a clean). log --raw lists every add or
117
+ # change, per commit, including merges (-m) and root commits.
118
+ foreach ($l in (MGit @('-c', 'core.quotePath=false', 'log', '--all', '--raw', '--no-abbrev', '--no-renames', '-m', '--root', '--format=', '--diff-filter=AMT'))) {
119
+ if (-not $l -or $l[0] -ne ':') { continue }
120
+ $meta, $p = $l -split "`t", 2
121
+ $f = $meta -split ' '
122
+ if ($f.Count -lt 4 -or -not $p -or $f[3] -match '^0+$') { continue }
123
+ # Mode 160000 is a submodule: its "blob" is a commit in ANOTHER repository, invisible to a
124
+ # size scan. Record it, so a runtime vendored as a submodule cannot pass unnoticed.
125
+ if ($f[1] -eq '160000') { [void]$submodules.Add($p); continue }
126
+ Add-PathForSha $f[3] $p
127
+ }
128
+ # Safety net: anything reachable that the log did not show.
129
+ foreach ($l in (MGit @('rev-list', '--objects', '--all'))) {
130
+ $sha, $p = $l -split ' ', 2
131
+ if ($p -and -not $pathsBySha.ContainsKey($sha)) { Add-PathForSha $sha $p }
132
+ }
133
+ $sizeBySha = @{}
134
+ foreach ($l in (MGit @('cat-file', '--batch-all-objects', '--batch-check=%(objecttype) %(objectname) %(objectsize)'))) {
135
+ $t, $o, $s = $l -split ' '
136
+ if ($t -eq 'blob' -and $pathsBySha.ContainsKey($o)) { $sizeBySha[$o] = [int64]$s }
137
+ }
138
+
139
+ # Aggregate per path: largest version, number of versions.
140
+ $byPath = @{}
141
+ foreach ($sha in $sizeBySha.Keys) {
142
+ foreach ($p in $pathsBySha[$sha]) {
143
+ if (-not $byPath.ContainsKey($p)) { $byPath[$p] = [pscustomobject]@{ path = $p; maxBytes = [int64]0; versions = 0 } }
144
+ $e = $byPath[$p]; $e.versions++
145
+ if ($sizeBySha[$sha] -gt $e.maxBytes) { $e.maxBytes = $sizeBySha[$sha] }
146
+ }
147
+ }
148
+
149
+ $tipFiles = @{}
150
+ foreach ($l in (MGit @('-c', 'core.quotePath=false', 'ls-tree', '-r', '--name-only', $branch))) { $tipFiles[$l] = $true }
151
+
152
+ # ---- classify ----------------------------------------------------------------------------------
153
+ $findings = New-Object System.Collections.Generic.List[object]
154
+ foreach ($e in $byPath.Values) {
155
+ $cat = Get-Category $e.path $e.maxBytes
156
+ if (-not $cat) { continue }
157
+ $findings.Add([pscustomobject]@{
158
+ path = $e.path; category = $cat; maxBytes = $e.maxBytes; versions = $e.versions
159
+ inDefaultBranch = [bool]$tipFiles[$e.path]
160
+ action = if ($cat -eq 'large-review') { 'review' } else { 'exclude' }
161
+ })
162
+ }
163
+ foreach ($sm in $submodules) {
164
+ $findings.Add([pscustomobject]@{ path = $sm; category = 'submodule'; maxBytes = [int64]0; versions = 1; inDefaultBranch = [bool]$tipFiles[$sm]; action = 'review' })
165
+ }
166
+ $exclude = @($findings | Where-Object { $_.action -eq 'exclude' })
167
+ $review = @($findings | Where-Object { $_.action -eq 'review' })
168
+
169
+ # Group by top two path segments so a 3,000-file vendored runtime reads as one line.
170
+ # Group by folder, at most 4 levels deep, so one vendored runtime reads as one line and a
171
+ # data folder deep in an app is still named precisely.
172
+ function Get-Group([string]$p) { $s = $p -split '/'; if ($s.Count -le 1) { return $p }; $d = $s[0..([math]::Min(3, $s.Count - 2))]; ($d -join '/') + '/' }
173
+ $groups = @($findings | Group-Object { "$($_.category)|$(Get-Group $_.path)" } | ForEach-Object {
174
+ $cat, $grp = $_.Name -split '\|', 2
175
+ [pscustomobject]@{
176
+ category = $cat; group = $grp; files = $_.Count
177
+ historyMB = [math]::Round((($_.Group | Measure-Object maxBytes -Sum).Sum) / 1MB, 1)
178
+ inDefaultBranch = @($_.Group | Where-Object { $_.inDefaultBranch }).Count
179
+ }
180
+ } | Sort-Object historyMB -Descending)
181
+
182
+ $totalBytes = [int64]0; foreach ($v in $sizeBySha.Values) { $totalBytes += $v }
183
+ # Count each blob once, even when it sits at several excluded paths (a per-path sum can exceed
184
+ # the whole history). Plain loops: Measure-Object on NO input has no .Sum under strict mode.
185
+ $exPaths = New-Object System.Collections.Generic.HashSet[string]
186
+ foreach ($x in $exclude) { [void]$exPaths.Add($x.path) }
187
+ $exBytes = [int64]0
188
+ foreach ($sha in $sizeBySha.Keys) { foreach ($p in $pathsBySha[$sha]) { if ($exPaths.Contains($p)) { $exBytes += $sizeBySha[$sha]; break } } }
189
+ $report = [ordered]@{
190
+ name = $Name; defaultBranch = $branch; checkedAt = (Get-Date).ToString('o')
191
+ thresholds = [ordered]@{ dataThresholdMB = $DataThresholdMB; largeMB = $LargeMB }
192
+ historyBlobMB = [math]::Round($totalBytes / 1MB, 1)
193
+ excludedPaths = $exclude.Count; excludedMB = [math]::Round($exBytes / 1MB, 1)
194
+ reviewPaths = $review.Count
195
+ compliant = ($exclude.Count -eq 0)
196
+ groups = $groups
197
+ findings = @($findings | Sort-Object maxBytes -Descending)
198
+ }
199
+ ConvertTo-PortJsonFile $report (Join-Path $stage 'content-policy.json')
200
+ # Plain path list, one per line, for Invoke-PortHistoryClean.ps1 and for .gitignore review.
201
+ Set-Content -LiteralPath (Join-Path $stage 'content-policy-exclude.txt') -Value @($exclude | Sort-Object path | ForEach-Object { $_.path }) -Encoding UTF8
202
+
203
+ Write-Host ''
204
+ Write-Host ("Content policy for {0}: {1} excluded path(s), {2} MB of history; {3} path(s) to review. History holds {4} MB of blobs in total." -f $Name, $exclude.Count, $report.excludedMB, $review.Count, $report.historyBlobMB)
205
+ if ($groups.Count -gt 0) {
206
+ Write-Host ''
207
+ Write-Host ('{0,-13} {1,-55} {2,7} {3,10} {4}' -f 'category', 'where', 'files', 'MB', 'in default branch')
208
+ foreach ($g in $groups) { Write-Host ('{0,-13} {1,-55} {2,7} {3,10} {4}' -f $g.category, $g.group, $g.files, $g.historyMB, $g.inDefaultBranch) }
209
+ }
210
+ if ($Detail) { $findings | Sort-Object maxBytes -Descending | ForEach-Object { Write-Host (' {0,-13} {1,9:N0} KB {2}' -f $_.category, ($_.maxBytes / 1KB), $_.path) } }
211
+ Write-Host " report: $(Join-Path $stage 'content-policy.json')"
212
+ Write-Host " exclude list: $(Join-Path $stage 'content-policy-exclude.txt')"
213
+ if ($exclude.Count -gt 0) {
214
+ Write-PortWarn 'Not compliant. Decide per group: keep (add a "keep" regex to contentPolicy), or remove from history with Invoke-PortHistoryClean.ps1. Adding a path to .gitignore does NOT remove it from history.'
215
+ exit 1
216
+ }
217
+ Write-PortOk 'Compliant: no excluded content anywhere in history.'
218
+ exit 0
@@ -1,8 +1,8 @@
1
1
  {
2
- "poolVersion": "1.3.112",
2
+ "poolVersion": "1.3.113",
3
3
  "bundles": {
4
- "antigravity-plugin": "1.3.112",
5
- "antigravity-plugin-extras": "1.3.33",
4
+ "antigravity-plugin": "1.3.113",
5
+ "antigravity-plugin-extras": "1.3.34",
6
6
  "codex": "unknown"
7
7
  }
8
8
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@caddis/cli",
3
- "version": "0.4.22",
3
+ "version": "0.4.24",
4
4
  "description": "Install, update and diagnose the caddis dev harness across every coding agent you use (Claude Code, agy/Antigravity, and more).",
5
5
  "keywords": [
6
6
  "caddis",