@ojokesusu/lintasai 1.1.2 → 1.2.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/.gitignore +55 -0
- package/AGENTS.md.template +91 -0
- package/CHANGELOG.md +64 -0
- package/bin/lintasai.js +22 -3
- package/docs/NPX_INSTALL.md +217 -0
- package/kit.ps1 +139 -5
- package/lib/kit-files.psd1 +0 -1
- package/package.json +8 -2
- package/setup-pola-b.ps1 +51 -2
- package/tests/npx-init.Tests.ps1 +237 -0
- package/tests/package-bundle.Tests.ps1 +130 -0
- package/tests/setup-pola-b.Tests.ps1 +280 -0
- package/uninstall.ps1 +13 -2
- package/update-kit.ps1 +15 -2
- package/FIRST_SESSION_PROMPT_v1.md +0 -7
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
#Requires -Module Pester
|
|
2
|
+
|
|
3
|
+
<#
|
|
4
|
+
.SYNOPSIS
|
|
5
|
+
Pester 5+ tests untuk setup-pola-b.ps1 (ProjectRoot resolution + npx mode copy).
|
|
6
|
+
|
|
7
|
+
.DESCRIPTION
|
|
8
|
+
Empat invocation branches yang di-test:
|
|
9
|
+
1. No -ProjectRoot, kit at <tmp>/.claude-kit/setup-pola-b.ps1
|
|
10
|
+
-> project = parent of kit (traditional Pola B mode).
|
|
11
|
+
2. -ProjectRoot supplied (valid path)
|
|
12
|
+
-> project = that explicit path (no derivation).
|
|
13
|
+
3. -ProjectRoot non-existent path
|
|
14
|
+
-> script errors out clearly (not silent fail). Resolve-Path -ErrorAction Stop
|
|
15
|
+
melempar terminating error; test assert exit code non-zero.
|
|
16
|
+
4. -ProjectRoot supplied + kit at npm-cache-like path (TEMP\nodemod-test\@ojokesusu\lintasai)
|
|
17
|
+
-> npx mode auto-detect, kit di-COPY ke $ProjectRoot/.claude-kit/.
|
|
18
|
+
|
|
19
|
+
Plus:
|
|
20
|
+
5. Manifest sanity: setelah setup sukses, .install-manifest.json terbuat.
|
|
21
|
+
|
|
22
|
+
Strategi:
|
|
23
|
+
- Real kit (parent dari folder tests/) jadi source-of-truth file.
|
|
24
|
+
- Per-test fake project root di $env:TEMP dengan layout sesuai branch.
|
|
25
|
+
- Branch 1, 2, 4, 5: pakai -Force -SkipTeamFiles untuk skip prompt + faster run.
|
|
26
|
+
- Branch 3: pakai path yang sengaja tidak ada, assert exit != 0 + pesan error.
|
|
27
|
+
- Test memanggil script di child PowerShell -NoProfile -NonInteractive supaya
|
|
28
|
+
env caller tidak ke-pollute (Set-StrictMode di lib/manifest.ps1 dll).
|
|
29
|
+
#>
|
|
30
|
+
|
|
31
|
+
BeforeAll {
|
|
32
|
+
# ---- Resolve repo root (kit folder asli, parent dari tests/) ----
|
|
33
|
+
$script:KitRepoRoot = Resolve-Path (Join-Path $PSScriptRoot '..') | Select-Object -ExpandProperty Path
|
|
34
|
+
$script:SetupScript = Join-Path $script:KitRepoRoot 'setup-pola-b.ps1'
|
|
35
|
+
|
|
36
|
+
if (-not (Test-Path $script:SetupScript)) {
|
|
37
|
+
throw "setup-pola-b.ps1 not found at $script:SetupScript - tests assume layout tests/ sibling to setup-pola-b.ps1"
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
# ---- Helper: copy kit asli ke target folder (jadi .claude-kit di fake project) ----
|
|
41
|
+
function script:Copy-RealKit {
|
|
42
|
+
param(
|
|
43
|
+
[Parameter(Mandatory)][string]$Destination
|
|
44
|
+
)
|
|
45
|
+
if (-not (Test-Path -LiteralPath $Destination)) {
|
|
46
|
+
$null = New-Item -ItemType Directory -Path $Destination -Force
|
|
47
|
+
}
|
|
48
|
+
# Copy semua isi kit kecuali subfolder yang bisa bikin loop/lambat (kalau ada)
|
|
49
|
+
Get-ChildItem -Path $script:KitRepoRoot -Force | Where-Object {
|
|
50
|
+
$_.Name -notin @('.git', 'node_modules')
|
|
51
|
+
} | ForEach-Object {
|
|
52
|
+
$dest = Join-Path $Destination $_.Name
|
|
53
|
+
if ($_.PSIsContainer) {
|
|
54
|
+
Copy-Item -LiteralPath $_.FullName -Destination $dest -Recurse -Force
|
|
55
|
+
} else {
|
|
56
|
+
Copy-Item -LiteralPath $_.FullName -Destination $dest -Force
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
# ---- Helper: bikin file dummy supaya proyek "tidak hampir kosong" ----
|
|
62
|
+
# setup-pola-b.ps1 skip docs/ skeleton kalau project root hampir kosong (heuristic
|
|
63
|
+
# menghitung non-hidden file/dir). Test branch 1/2/4/5 mau real flow, jadi taruh
|
|
64
|
+
# 2 file dummy supaya nonHiddenFiles.Count > 1.
|
|
65
|
+
function script:Add-ProjectContent {
|
|
66
|
+
param([Parameter(Mandatory)][string]$Root)
|
|
67
|
+
[System.IO.File]::WriteAllText(
|
|
68
|
+
(Join-Path $Root 'README.md'),
|
|
69
|
+
"# Test Project`nDummy content untuk lewatin proyek-hampir-kosong heuristic.`n",
|
|
70
|
+
(New-Object System.Text.UTF8Encoding $false)
|
|
71
|
+
)
|
|
72
|
+
[System.IO.File]::WriteAllText(
|
|
73
|
+
(Join-Path $Root 'package.json'),
|
|
74
|
+
'{"name":"test","version":"0.0.1"}',
|
|
75
|
+
(New-Object System.Text.UTF8Encoding $false)
|
|
76
|
+
)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
# ---- Helper: run setup-pola-b.ps1 di child PowerShell, capture stdout + exit ----
|
|
80
|
+
function script:Invoke-Setup {
|
|
81
|
+
param(
|
|
82
|
+
[Parameter(Mandatory)][string]$ScriptPath,
|
|
83
|
+
[string[]]$Args = @()
|
|
84
|
+
)
|
|
85
|
+
$pwshExe = (Get-Process -Id $PID).Path
|
|
86
|
+
if (-not $pwshExe) { $pwshExe = 'powershell.exe' }
|
|
87
|
+
$allArgs = @('-NoProfile', '-NonInteractive', '-ExecutionPolicy', 'Bypass', '-File', $ScriptPath) + $Args
|
|
88
|
+
$output = & $pwshExe @allArgs 2>&1 | Out-String
|
|
89
|
+
return [pscustomobject]@{
|
|
90
|
+
Output = $output
|
|
91
|
+
ExitCode = $LASTEXITCODE
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
# ---- Helper: cleanup folder kalau ada ----
|
|
96
|
+
function script:Remove-TestRoot {
|
|
97
|
+
param([Parameter(Mandatory)][string]$Path)
|
|
98
|
+
if (Test-Path -LiteralPath $Path) {
|
|
99
|
+
Remove-Item -Recurse -Force -LiteralPath $Path -ErrorAction SilentlyContinue
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
Describe "setup-pola-b.ps1 Branch 1: traditional invocation (no -ProjectRoot)" {
|
|
105
|
+
BeforeAll {
|
|
106
|
+
# Layout: <tmp>/<project>/.claude-kit/setup-pola-b.ps1
|
|
107
|
+
$script:Root1 = Join-Path $env:TEMP ("lintasAI-setup-test-traditional-{0}" -f ([guid]::NewGuid().ToString('N').Substring(0,8)))
|
|
108
|
+
$null = New-Item -ItemType Directory -Path $script:Root1 -Force
|
|
109
|
+
script:Add-ProjectContent -Root $script:Root1
|
|
110
|
+
$script:Kit1 = Join-Path $script:Root1 '.claude-kit'
|
|
111
|
+
script:Copy-RealKit -Destination $script:Kit1
|
|
112
|
+
$script:SetupInKit1 = Join-Path $script:Kit1 'setup-pola-b.ps1'
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
AfterAll {
|
|
116
|
+
script:Remove-TestRoot -Path $script:Root1
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
It "Resolves project root = parent of kit folder" {
|
|
120
|
+
$result = script:Invoke-Setup -ScriptPath $script:SetupInKit1 -Args @('-Force', '-SkipTeamFiles')
|
|
121
|
+
$result.ExitCode | Should -Be 0
|
|
122
|
+
# Output harus mention root proyek sesuai $Root1.
|
|
123
|
+
$result.Output | Should -Match ([regex]::Escape($script:Root1))
|
|
124
|
+
# AGENTS.md harus dideploy di project root.
|
|
125
|
+
(Test-Path -LiteralPath (Join-Path $script:Root1 'AGENTS.md')) | Should -BeTrue
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
It "Does NOT print npx mode banner" {
|
|
129
|
+
# Traditional mode: tidak boleh ada string "[npx] Mode" karena ProjectRoot tidak di-pass.
|
|
130
|
+
# Re-run dengan -DryRun supaya tidak duplicate setup di same root.
|
|
131
|
+
$result = script:Invoke-Setup -ScriptPath $script:SetupInKit1 -Args @('-Force', '-SkipTeamFiles', '-DryRun')
|
|
132
|
+
$result.Output | Should -Not -Match '\[npx\] Mode'
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
Describe "setup-pola-b.ps1 Branch 2: -ProjectRoot supplied (valid path)" {
|
|
137
|
+
BeforeAll {
|
|
138
|
+
# Layout: <tmp>/<project>/.claude-kit/setup-pola-b.ps1 (kit lives standard place)
|
|
139
|
+
# but we ALSO pass -ProjectRoot explicitly to exercise the npx-mode code path
|
|
140
|
+
# bahkan kalau path-nya same. Script harus treat sebagai npx mode.
|
|
141
|
+
$script:Root2 = Join-Path $env:TEMP ("lintasAI-setup-test-explicitroot-{0}" -f ([guid]::NewGuid().ToString('N').Substring(0,8)))
|
|
142
|
+
$null = New-Item -ItemType Directory -Path $script:Root2 -Force
|
|
143
|
+
script:Add-ProjectContent -Root $script:Root2
|
|
144
|
+
$script:Kit2 = Join-Path $script:Root2 '.claude-kit'
|
|
145
|
+
script:Copy-RealKit -Destination $script:Kit2
|
|
146
|
+
$script:SetupInKit2 = Join-Path $script:Kit2 'setup-pola-b.ps1'
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
AfterAll {
|
|
150
|
+
script:Remove-TestRoot -Path $script:Root2
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
It "Uses the explicit ProjectRoot path (no derivation)" {
|
|
154
|
+
$result = script:Invoke-Setup -ScriptPath $script:SetupInKit2 -Args @(
|
|
155
|
+
'-Force', '-SkipTeamFiles', '-ProjectRoot', $script:Root2
|
|
156
|
+
)
|
|
157
|
+
$result.ExitCode | Should -Be 0
|
|
158
|
+
# Banner npx mode harus muncul (proves the branch executed).
|
|
159
|
+
$result.Output | Should -Match '\[npx\] Mode: explicit ProjectRoot'
|
|
160
|
+
# AGENTS.md harus ada di explicit root.
|
|
161
|
+
(Test-Path -LiteralPath (Join-Path $script:Root2 'AGENTS.md')) | Should -BeTrue
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
Describe "setup-pola-b.ps1 Branch 3: -ProjectRoot non-existent path" {
|
|
166
|
+
BeforeAll {
|
|
167
|
+
# Kit lives di TEMP/<kit-folder>/.claude-kit dengan parent project legit, tapi
|
|
168
|
+
# we pass -ProjectRoot ke path yang tidak ada -> Resolve-Path -ErrorAction Stop
|
|
169
|
+
# harus throw -> exit code non-zero, with clear error message (not silent).
|
|
170
|
+
$script:Root3 = Join-Path $env:TEMP ("lintasAI-setup-test-badroot-{0}" -f ([guid]::NewGuid().ToString('N').Substring(0,8)))
|
|
171
|
+
$null = New-Item -ItemType Directory -Path $script:Root3 -Force
|
|
172
|
+
script:Add-ProjectContent -Root $script:Root3
|
|
173
|
+
$script:Kit3 = Join-Path $script:Root3 '.claude-kit'
|
|
174
|
+
script:Copy-RealKit -Destination $script:Kit3
|
|
175
|
+
$script:SetupInKit3 = Join-Path $script:Kit3 'setup-pola-b.ps1'
|
|
176
|
+
# Path yang DIJAMIN tidak ada
|
|
177
|
+
$script:BadRoot = Join-Path $env:TEMP ("lintasAI-DOES-NOT-EXIST-{0}" -f ([guid]::NewGuid().ToString('N').Substring(0,8)))
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
AfterAll {
|
|
181
|
+
script:Remove-TestRoot -Path $script:Root3
|
|
182
|
+
script:Remove-TestRoot -Path $script:BadRoot # defensive (script harusnya tidak create)
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
It "Errors out (non-zero exit) with clear message" {
|
|
186
|
+
$result = script:Invoke-Setup -ScriptPath $script:SetupInKit3 -Args @(
|
|
187
|
+
'-Force', '-SkipTeamFiles', '-ProjectRoot', $script:BadRoot
|
|
188
|
+
)
|
|
189
|
+
$result.ExitCode | Should -Not -Be 0
|
|
190
|
+
# Pesan harus include "Resolve-Path" / "not exist" / nama path yang tidak valid -
|
|
191
|
+
# apa pun yang membuktikan ini BUKAN silent fail.
|
|
192
|
+
# Resolve-Path throws "Cannot find path '...' because it does not exist."
|
|
193
|
+
$result.Output | Should -Match '(?i)(cannot find path|does not exist|not exist|tidak ditemukan|tidak ada)'
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
It "Does NOT create .claude-kit at the bogus path" {
|
|
197
|
+
# Script tidak boleh men-create folder di path yang tidak ada (defensive guard).
|
|
198
|
+
(Test-Path -LiteralPath $script:BadRoot) | Should -BeFalse
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
Describe "setup-pola-b.ps1 Branch 4: -ProjectRoot + kit at npm-cache-like path" {
|
|
203
|
+
BeforeAll {
|
|
204
|
+
# Layout simulasi npx:
|
|
205
|
+
# <tmp>\nodemod-test\@ojokesusu\lintasai\setup-pola-b.ps1 (kit di npm cache)
|
|
206
|
+
# <tmp>\<project-root>\ (target project, beda parent)
|
|
207
|
+
# Script harus detect mismatch ($KitDir tidak dalam $ProjectRoot/.claude-kit/)
|
|
208
|
+
# dan COPY isi kit ke $ProjectRoot/.claude-kit/.
|
|
209
|
+
$script:Root4 = Join-Path $env:TEMP ("lintasAI-setup-test-npx-{0}" -f ([guid]::NewGuid().ToString('N').Substring(0,8)))
|
|
210
|
+
$null = New-Item -ItemType Directory -Path $script:Root4 -Force
|
|
211
|
+
script:Add-ProjectContent -Root $script:Root4
|
|
212
|
+
|
|
213
|
+
# Kit DIPASANG di npm-cache-like location (BUKAN di $script:Root4/.claude-kit)
|
|
214
|
+
$script:NpmCacheRoot = Join-Path $env:TEMP ("nodemod-test-{0}" -f ([guid]::NewGuid().ToString('N').Substring(0,8)))
|
|
215
|
+
$script:KitInNpmCache = Join-Path $script:NpmCacheRoot '@ojokesusu\lintasai'
|
|
216
|
+
$null = New-Item -ItemType Directory -Path $script:KitInNpmCache -Force
|
|
217
|
+
script:Copy-RealKit -Destination $script:KitInNpmCache
|
|
218
|
+
$script:SetupInNpmCache = Join-Path $script:KitInNpmCache 'setup-pola-b.ps1'
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
AfterAll {
|
|
222
|
+
script:Remove-TestRoot -Path $script:Root4
|
|
223
|
+
script:Remove-TestRoot -Path $script:NpmCacheRoot
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
It "Detects npx mode and copies kit to <ProjectRoot>/.claude-kit/" {
|
|
227
|
+
# Pre-assert: target .claude-kit tidak ada sebelum jalan.
|
|
228
|
+
$targetKit = Join-Path $script:Root4 '.claude-kit'
|
|
229
|
+
(Test-Path -LiteralPath $targetKit) | Should -BeFalse
|
|
230
|
+
|
|
231
|
+
$result = script:Invoke-Setup -ScriptPath $script:SetupInNpmCache -Args @(
|
|
232
|
+
'-Force', '-SkipTeamFiles', '-ProjectRoot', $script:Root4
|
|
233
|
+
)
|
|
234
|
+
$result.ExitCode | Should -Be 0
|
|
235
|
+
# Verifikasi log npx mode + copy
|
|
236
|
+
$result.Output | Should -Match '\[npx\] Mode: explicit ProjectRoot'
|
|
237
|
+
$result.Output | Should -Match '(?i)\[npx\] Copy kit'
|
|
238
|
+
|
|
239
|
+
# Hasil: .claude-kit di project root harus ada, berisi setup-pola-b.ps1 yang ke-copy
|
|
240
|
+
(Test-Path -LiteralPath $targetKit) | Should -BeTrue
|
|
241
|
+
(Test-Path -LiteralPath (Join-Path $targetKit 'setup-pola-b.ps1')) | Should -BeTrue
|
|
242
|
+
(Test-Path -LiteralPath (Join-Path $targetKit 'CHANGELOG.md')) | Should -BeTrue
|
|
243
|
+
(Test-Path -LiteralPath (Join-Path $targetKit 'lib\manifest.ps1')) | Should -BeTrue
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
Describe "setup-pola-b.ps1 manifest creation" {
|
|
248
|
+
BeforeAll {
|
|
249
|
+
# Reuse pattern Branch 1 (traditional) – setelah setup sukses, manifest harus
|
|
250
|
+
# terbuat di .claude-kit/.install-manifest.json. Pakai fresh root supaya hash
|
|
251
|
+
# & state-nya independent dari describe lain.
|
|
252
|
+
$script:Root5 = Join-Path $env:TEMP ("lintasAI-setup-test-manifest-{0}" -f ([guid]::NewGuid().ToString('N').Substring(0,8)))
|
|
253
|
+
$null = New-Item -ItemType Directory -Path $script:Root5 -Force
|
|
254
|
+
script:Add-ProjectContent -Root $script:Root5
|
|
255
|
+
$script:Kit5 = Join-Path $script:Root5 '.claude-kit'
|
|
256
|
+
script:Copy-RealKit -Destination $script:Kit5
|
|
257
|
+
$script:SetupInKit5 = Join-Path $script:Kit5 'setup-pola-b.ps1'
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
AfterAll {
|
|
261
|
+
script:Remove-TestRoot -Path $script:Root5
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
It "Creates .install-manifest.json after successful setup" {
|
|
265
|
+
$result = script:Invoke-Setup -ScriptPath $script:SetupInKit5 -Args @('-Force', '-SkipTeamFiles')
|
|
266
|
+
$result.ExitCode | Should -Be 0
|
|
267
|
+
$manifestPath = Join-Path $script:Kit5 '.install-manifest.json'
|
|
268
|
+
(Test-Path -LiteralPath $manifestPath) | Should -BeTrue
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
It "Manifest is valid JSON with expected top-level fields" {
|
|
272
|
+
$manifestPath = Join-Path $script:Kit5 '.install-manifest.json'
|
|
273
|
+
(Test-Path -LiteralPath $manifestPath) | Should -BeTrue
|
|
274
|
+
$json = Get-Content -LiteralPath $manifestPath -Raw -Encoding UTF8
|
|
275
|
+
{ $json | ConvertFrom-Json -ErrorAction Stop } | Should -Not -Throw
|
|
276
|
+
$obj = $json | ConvertFrom-Json
|
|
277
|
+
$obj.PSObject.Properties.Name | Should -Contain 'schema_version'
|
|
278
|
+
$obj.PSObject.Properties.Name | Should -Contain 'files'
|
|
279
|
+
}
|
|
280
|
+
}
|
package/uninstall.ps1
CHANGED
|
@@ -63,9 +63,20 @@ param(
|
|
|
63
63
|
[switch]$DeleteAgents,
|
|
64
64
|
[switch]$KeepKit,
|
|
65
65
|
[switch]$Yes,
|
|
66
|
-
[switch]$AllowProjectRootMismatch
|
|
66
|
+
[switch]$AllowProjectRootMismatch,
|
|
67
|
+
[string]$ProjectRoot = $null
|
|
67
68
|
)
|
|
68
69
|
|
|
70
|
+
# ---- Resolve $ProjectRoot early (param-driven, fallback to script location) ----
|
|
71
|
+
# Kalau user pass -ProjectRoot pakai itu (untuk smoke test / CI). Kalau tidak, derive dari
|
|
72
|
+
# $PSScriptRoot (script ada di .claude-kit\, parent = project root).
|
|
73
|
+
if (-not $ProjectRoot) {
|
|
74
|
+
$ProjectRoot = Split-Path -Parent $PSScriptRoot
|
|
75
|
+
} else {
|
|
76
|
+
$ProjectRoot = (Resolve-Path $ProjectRoot -ErrorAction Stop).Path
|
|
77
|
+
}
|
|
78
|
+
Write-Host "Root proyek : $ProjectRoot"
|
|
79
|
+
|
|
69
80
|
# ---- Deprecation handling: -Force jadi alias backward-compat untuk -AllowModified ----
|
|
70
81
|
# Sebelumnya -Force overloaded (modified bypass + signature bypass). Pisahkan supaya
|
|
71
82
|
# intent jelas. -Force masih bekerja untuk backward-compat tapi warn user.
|
|
@@ -81,8 +92,8 @@ if ($Force) {
|
|
|
81
92
|
$ErrorActionPreference = 'Stop'
|
|
82
93
|
|
|
83
94
|
# ---- Resolve folder kit (tempat script ini berada) ----
|
|
95
|
+
# $ProjectRoot sudah di-resolve di awal (param-driven). Jangan override.
|
|
84
96
|
$KitDir = if ($PSScriptRoot) { $PSScriptRoot } elseif ($MyInvocation.MyCommand.Path) { Split-Path -Parent $MyInvocation.MyCommand.Path } else { (Get-Location).Path }
|
|
85
|
-
$ProjectRoot = Split-Path -Parent $KitDir
|
|
86
97
|
$ProjectName = Split-Path -Leaf $ProjectRoot
|
|
87
98
|
$Timestamp = Get-Date -Format 'yyyyMMdd-HHmmss'
|
|
88
99
|
|
package/update-kit.ps1
CHANGED
|
@@ -70,11 +70,22 @@ param(
|
|
|
70
70
|
[switch]$DryRun,
|
|
71
71
|
[switch]$AllowUntrustedRepo,
|
|
72
72
|
[switch]$Force,
|
|
73
|
-
[switch]$AllowUnsignedTag
|
|
73
|
+
[switch]$AllowUnsignedTag,
|
|
74
|
+
[string]$ProjectRoot = $null
|
|
74
75
|
)
|
|
75
76
|
|
|
76
77
|
$ErrorActionPreference = 'Stop'
|
|
77
78
|
|
|
79
|
+
# ---- Resolve $ProjectRoot early (param-driven, fallback to script location) ----
|
|
80
|
+
# Kalau user pass -ProjectRoot pakai itu (untuk smoke test / CI). Kalau tidak, derive dari
|
|
81
|
+
# $PSScriptRoot (script ada di .claude-kit\, parent = project root).
|
|
82
|
+
if (-not $ProjectRoot) {
|
|
83
|
+
$ProjectRoot = Split-Path -Parent $PSScriptRoot
|
|
84
|
+
} else {
|
|
85
|
+
$ProjectRoot = (Resolve-Path $ProjectRoot -ErrorAction Stop).Path
|
|
86
|
+
}
|
|
87
|
+
Write-Host "Root proyek : $ProjectRoot"
|
|
88
|
+
|
|
78
89
|
# ---- Deprecation handling: -Force jadi alias backward-compat untuk -AllowUntrustedRepo ----
|
|
79
90
|
# Sebelumnya -Force overloaded (GPG bypass + RepoUrl bypass). GPG bypass sekarang lewat
|
|
80
91
|
# -AllowUnsignedTag; -Force narrowed jadi alias RepoUrl-allowlist-bypass saja, dengan warn.
|
|
@@ -89,9 +100,11 @@ if ($Force) {
|
|
|
89
100
|
}
|
|
90
101
|
|
|
91
102
|
# ---- Resolve paths (do this FIRST, sebelum Move-Item rename folder) ----
|
|
103
|
+
# $ProjectRoot (PascalCase) sudah di-resolve dari param di awal. $projectRoot (camelCase)
|
|
104
|
+
# di-alias supaya legacy code di bawah tetap jalan tanpa rename massal.
|
|
92
105
|
$kitDir = if ($PSScriptRoot) { $PSScriptRoot } elseif ($MyInvocation.MyCommand.Path) { Split-Path -Parent $MyInvocation.MyCommand.Path } else { (Get-Location).Path }
|
|
93
106
|
$kitFolderName = Split-Path -Leaf $kitDir
|
|
94
|
-
$projectRoot =
|
|
107
|
+
$projectRoot = $ProjectRoot
|
|
95
108
|
$timestamp = Get-Date -Format 'yyyyMMdd-HHmmss'
|
|
96
109
|
$backupDir = "$kitDir.backup-$timestamp"
|
|
97
110
|
|