@ojokesusu/lintasai 1.1.2
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/.github/workflows/publish-npm.yml +40 -0
- package/.github/workflows/validate.yml +93 -0
- package/AUDIT_POST_SETUP_PROMPT_v1.md +280 -0
- package/BOOTSTRAP_PROJECT_DOCS_PROMPT_v1.md +3 -0
- package/CHANGELOG.md +313 -0
- package/CLAUDE_universal_v1.md +1021 -0
- package/CONTRIBUTING.md +101 -0
- package/FIRST_SESSION_PROMPT_v1.md +7 -0
- package/JALANKAN_KIT.md +188 -0
- package/LICENSE +21 -0
- package/MULAI_DI_SINI.md +145 -0
- package/PROJECT_KICKOFF_PROMPT_v1.md +3 -0
- package/PROJECT_LIFECYCLE_PROMPT_v1.md +536 -0
- package/PROJECT_MIGRATION_PROMPT_v1.md +3 -0
- package/README.md +505 -0
- package/SETUP_POLA_B_PROMPT_v1.md +5 -0
- package/SPLIT_REPO_MIGRATION_PROMPT_v1.md +485 -0
- package/TEAM_ROLLOUT_GUIDE_v1.md +172 -0
- package/UPDATE_DOCS_PROMPT_v1.md +3 -0
- package/UPDATE_KIT_PROMPT_v1.md +213 -0
- package/bin/lintasai.js +81 -0
- package/docs/SIGNED_RELEASE.md +162 -0
- package/install-windows.ps1 +225 -0
- package/kit.ps1 +508 -0
- package/lib/agents-md.ps1 +174 -0
- package/lib/git-helpers.ps1 +104 -0
- package/lib/kit-files.psd1 +133 -0
- package/lib/manifest-signing.ps1 +65 -0
- package/lib/manifest.ps1 +267 -0
- package/lib/rollback.ps1 +241 -0
- package/lib/safety.ps1 +193 -0
- package/lib/template-deploy.ps1 +242 -0
- package/lib/version-detect.ps1 +161 -0
- package/package.json +36 -0
- package/setup-pola-b.ps1 +687 -0
- package/templates/ANALOGI_LIBRARY.md +7 -0
- package/templates/CLAUDE_TEAM_GUIDE.md +505 -0
- package/templates/CROSS_REPO_TYPES_PIPELINE.md +473 -0
- package/templates/DB_SCHEMA_SCAN_PROMPT.md +194 -0
- package/templates/DISCORD_BOT_INTEGRATION.md +187 -0
- package/templates/GLOSSARY_NON_PROGRAMMER.md +361 -0
- package/templates/INDEX.md +157 -0
- package/templates/MCP_SETUP.md +1145 -0
- package/templates/MIGRATE_TO_SUBFOLDER_PROMPT_v1.md +220 -0
- package/templates/ONBOARDING.md +172 -0
- package/templates/PROJECT_STARTER_TEMPLATES.md +264 -0
- package/templates/PROMPT_LIBRARY.md +790 -0
- package/templates/RLS_SETUP_PROMPT.md +167 -0
- package/templates/SECURITY_INCIDENT_PLAYBOOK.md +191 -0
- package/templates/SPLIT_REPO_AGENTS_TEMPLATES.md +32 -0
- package/templates/SPLIT_REPO_NON_PROGRAMMER_PROMPTS.md +604 -0
- package/templates/SPLIT_REPO_TOOLS_SETUP.md +388 -0
- package/templates/STACK_DETECTION_PATTERN.md +261 -0
- package/templates/STACK_GUIDE.md +564 -0
- package/templates/STACK_MIGRATION_GUIDE.md +154 -0
- package/templates/STACK_VERSIONS.md +31 -0
- package/templates/UPDATE_GUIDE.md +246 -0
- package/templates/_EXAMPLE.md +110 -0
- package/templates/_PATTERNS.md +173 -0
- package/templates/architecture.md +180 -0
- package/templates/architecture_auto.md +61 -0
- package/templates/decisions/README.md +108 -0
- package/templates/decisions/_TEMPLATE.md +84 -0
- package/templates/feature-flags-advanced.md +171 -0
- package/templates/github/CODEOWNERS.template +61 -0
- package/templates/github/GENERATE_TYPES_SCRIPT.md +77 -0
- package/templates/github/PUBLISH_SHARED_WORKFLOW.yml +52 -0
- package/templates/github/RECEIVE_BACKEND_UPDATE.yml +106 -0
- package/templates/github/RENOVATE_FRONTEND.json +28 -0
- package/templates/github/TRIGGER_FRONTEND_UPDATE.yml +29 -0
- package/templates/github/pull_request_template.md +44 -0
- package/templates/github/scripts/ai-review.js +153 -0
- package/templates/github/workflows/ai-review.yml +61 -0
- package/templates/github/workflows/backup-schemas.yml +169 -0
- package/templates/glossary.md +110 -0
- package/templates/split-agents/BACKEND.md +149 -0
- package/templates/split-agents/FRONTEND.md +141 -0
- package/templates/split-agents/SHARED.md +82 -0
- package/templates/split-agents/TOOLS.md +77 -0
- package/tests/Run-Tests.ps1 +19 -0
- package/tests/lib-safety.Tests.ps1 +66 -0
- package/tests/rollback.Tests.ps1 +66 -0
- package/tests/uninstall.Tests.ps1 +265 -0
- package/tests/update-kit.Tests.ps1 +78 -0
- package/uninstall.ps1 +794 -0
- package/update-kit.ps1 +907 -0
package/setup-pola-b.ps1
ADDED
|
@@ -0,0 +1,687 @@
|
|
|
1
|
+
<#
|
|
2
|
+
.SYNOPSIS
|
|
3
|
+
setup-pola-b.ps1 - Setup Pola B di root proyek (kit embed sebagai subfolder)
|
|
4
|
+
.DESCRIPTION
|
|
5
|
+
Asumsi: kamu sudah extract zip kit ini jadi <proyek>\.claude-kit\, lalu jalanin
|
|
6
|
+
script ini dari folder <proyek>\.claude-kit\.
|
|
7
|
+
|
|
8
|
+
Script ini ORCHESTRATOR — heavy-lifting di delegate ke lib/*.ps1:
|
|
9
|
+
- lib\manifest.ps1 : Initialize/Add/Save manifest (.install-manifest.json)
|
|
10
|
+
- lib\template-deploy.ps1 : Copy template + placeholder substitution
|
|
11
|
+
- lib\git-helpers.ps1 : Strip .git + Unblock MOTW
|
|
12
|
+
- lib\agents-md.ps1 : Deploy AGENTS.md (template fill + backup)
|
|
13
|
+
- lib\version-detect.ps1 : Parse versi kit dari CHANGELOG.md
|
|
14
|
+
- lib\manifest-signing.ps1 : HMAC sign manifest (loaded via Save-Manifest)
|
|
15
|
+
- lib\safety.ps1 : Path safety helpers
|
|
16
|
+
|
|
17
|
+
Tugas orchestrator:
|
|
18
|
+
1. Project root validation + nested-extract detection
|
|
19
|
+
2. Interactive prompts (popup CLAUDE.md, nama, repo, AGENTS.md overwrite)
|
|
20
|
+
3. Verifikasi file inti kit ada (via lib\kit-files.psd1)
|
|
21
|
+
4. Call lib functions untuk actual deploy
|
|
22
|
+
5. Final summary report
|
|
23
|
+
|
|
24
|
+
TIDAK install ke ~/.claude/ (itu Pola Global, pakai install-windows.ps1).
|
|
25
|
+
.PARAMETER Force
|
|
26
|
+
Timpa AGENTS.md yang sudah ada (backup otomatis ke .backup-<timestamp>).
|
|
27
|
+
Saat -Force aktif, prompt opsional Nama/URL repo di-skip (placeholder default dipakai).
|
|
28
|
+
.PARAMETER DryRun
|
|
29
|
+
Tampilkan rencana aksi tanpa nulis/copy file apapun.
|
|
30
|
+
.NOTES
|
|
31
|
+
Versi : 2.0 (orchestrator refactor, 2026-06-06)
|
|
32
|
+
Run : powershell -ExecutionPolicy Bypass -File .\setup-pola-b.ps1
|
|
33
|
+
Atau : cd <proyek>\.claude-kit; .\setup-pola-b.ps1
|
|
34
|
+
Lebih ringkas: .\.claude-kit\kit.ps1 setup
|
|
35
|
+
#>
|
|
36
|
+
|
|
37
|
+
[CmdletBinding()]
|
|
38
|
+
param(
|
|
39
|
+
[switch]$Force,
|
|
40
|
+
[switch]$DryRun,
|
|
41
|
+
[switch]$SkipTeamFiles
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
$ErrorActionPreference = 'Stop'
|
|
45
|
+
|
|
46
|
+
# ---- Resolve folder kit (tempat script ini berada) ----
|
|
47
|
+
$KitDir = if ($PSScriptRoot) { $PSScriptRoot } elseif ($MyInvocation.MyCommand.Path) { Split-Path -Parent $MyInvocation.MyCommand.Path } else { (Get-Location).Path }
|
|
48
|
+
|
|
49
|
+
# ---- Dot-source library helpers (heavy-lifting) ----
|
|
50
|
+
# Order penting: agents-md.ps1 dot-source SEBELUM manifest.ps1.
|
|
51
|
+
# agents-md.ps1 punya guard `if ($script:__lintasAI_AgentsMdLoaded)` (anti-redefine).
|
|
52
|
+
# manifest.ps1 set `Set-StrictMode -Version Latest` yang kebawa ke caller scope —
|
|
53
|
+
# strict mode reject access ke variable yang belum di-set. Kalau order kebalik,
|
|
54
|
+
# guard agents-md crash karena `$script:__lintasAI_AgentsMdLoaded` belum ada.
|
|
55
|
+
$script:__lintasAI_AgentsMdLoaded = $null
|
|
56
|
+
. (Join-Path $KitDir 'lib\safety.ps1')
|
|
57
|
+
. (Join-Path $KitDir 'lib\agents-md.ps1')
|
|
58
|
+
. (Join-Path $KitDir 'lib\template-deploy.ps1')
|
|
59
|
+
. (Join-Path $KitDir 'lib\git-helpers.ps1')
|
|
60
|
+
. (Join-Path $KitDir 'lib\version-detect.ps1')
|
|
61
|
+
. (Join-Path $KitDir 'lib\manifest.ps1')
|
|
62
|
+
# manifest-signing.ps1 di-load on-demand oleh Save-Manifest (lib\manifest.ps1)
|
|
63
|
+
|
|
64
|
+
# ---- Deteksi NESTED extract (zip extract jadi folder dalam folder) ----
|
|
65
|
+
# Skenario: Windows Explorer "Extract All" sering bikin .claude-kit\<kit-folder>\...
|
|
66
|
+
$kitFolderName = Split-Path -Leaf $KitDir
|
|
67
|
+
$parentDir = Split-Path -Parent $KitDir
|
|
68
|
+
$parentFolderName = Split-Path -Leaf $parentDir
|
|
69
|
+
|
|
70
|
+
if ($kitFolderName -ne '.claude-kit' -and $parentFolderName -eq '.claude-kit') {
|
|
71
|
+
Write-Host "DETEKSI: Kit ter-extract NESTED - script ada di '$kitFolderName' di dalam '.claude-kit'." -ForegroundColor Yellow
|
|
72
|
+
Write-Host " Ini biasa terjadi kalau extract pakai Windows Explorer (Extract All)." -ForegroundColor Yellow
|
|
73
|
+
Write-Host ""
|
|
74
|
+
|
|
75
|
+
if (-not $Force -and -not $DryRun) {
|
|
76
|
+
# Wrap Read-Host di try/catch — gracefully handle NonInteractive shell.
|
|
77
|
+
# Default ke 'N' (abort, jangan auto-flatten destruktif tanpa user consent).
|
|
78
|
+
$autoFix = 'N'
|
|
79
|
+
try {
|
|
80
|
+
$autoFix = Read-Host "Mau aku auto-flatten? (pindahkan isi '$kitFolderName' ke '.claude-kit', hapus folder kosong) [Y/N]"
|
|
81
|
+
} catch {
|
|
82
|
+
Write-Host "INFO: Shell NonInteractive terdeteksi. Auto-flatten butuh konfirmasi user — abort." -ForegroundColor Yellow
|
|
83
|
+
Write-Host " Jalankan di PowerShell window untuk pilih Y/N, atau pakai -Force untuk auto-yes." -ForegroundColor Yellow
|
|
84
|
+
$autoFix = 'N'
|
|
85
|
+
}
|
|
86
|
+
if ($autoFix -notmatch '^[Yy]') {
|
|
87
|
+
Write-Host "Dibatalkan. Untuk fix manual:" -ForegroundColor Yellow
|
|
88
|
+
Write-Host " 1. Pindahkan SEMUA isi '$KitDir' ke parent '$parentDir'." -ForegroundColor Yellow
|
|
89
|
+
Write-Host " 2. Hapus folder kosong '$KitDir'." -ForegroundColor Yellow
|
|
90
|
+
Write-Host " 3. Jalankan ulang setup-pola-b.ps1 dari '$parentDir\setup-pola-b.ps1'." -ForegroundColor Yellow
|
|
91
|
+
exit 1
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if ($DryRun) {
|
|
96
|
+
Write-Host "[DRY] Akan flatten: pindahkan '$KitDir\*' ke '$parentDir\', hapus '$KitDir'." -ForegroundColor Yellow
|
|
97
|
+
Write-Host "[DRY] Setelah flatten, validasi 13 file inti + setup AGENTS.md akan jalan dari '$parentDir'." -ForegroundColor Yellow
|
|
98
|
+
Write-Host ""
|
|
99
|
+
Write-Host "Mode DRY-RUN: berhenti setelah preview nested. Jalankan ulang tanpa -DryRun untuk eksekusi sungguhan." -ForegroundColor Cyan
|
|
100
|
+
exit 0
|
|
101
|
+
} else {
|
|
102
|
+
try {
|
|
103
|
+
Write-Host "FLATTEN: $KitDir\* -> $parentDir\" -ForegroundColor Cyan
|
|
104
|
+
Get-ChildItem -Path $KitDir -Force | Move-Item -Destination $parentDir -Force
|
|
105
|
+
Remove-Item -Path $KitDir -Recurse -Force
|
|
106
|
+
Write-Host "OK Flatten selesai." -ForegroundColor Green
|
|
107
|
+
$KitDir = $parentDir
|
|
108
|
+
$kitFolderName = Split-Path -Leaf $KitDir
|
|
109
|
+
Write-Host ""
|
|
110
|
+
} catch {
|
|
111
|
+
Write-Host "GAGAL flatten: $_" -ForegroundColor Red
|
|
112
|
+
Write-Host " Fix manual: pindahkan isi $KitDir ke parent, hapus folder kosong." -ForegroundColor Red
|
|
113
|
+
$sisaFiles = Get-ChildItem -Path $KitDir -Force -ErrorAction SilentlyContinue
|
|
114
|
+
if ($sisaFiles) {
|
|
115
|
+
Write-Host " File yang masih di ${KitDir}:" -ForegroundColor Yellow
|
|
116
|
+
$sisaFiles | ForEach-Object { Write-Host " $($_.Name)" -ForegroundColor Yellow }
|
|
117
|
+
}
|
|
118
|
+
exit 1
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
# ---- Validasi: kit harus berada di subfolder bernama .claude-kit ----
|
|
124
|
+
if ($kitFolderName -ne '.claude-kit') {
|
|
125
|
+
Write-Host "PERINGATAN: Folder kit ini bernama '$kitFolderName', bukan '.claude-kit'." -ForegroundColor Yellow
|
|
126
|
+
Write-Host " Pola B mengasumsikan kit ada di '<proyek>\.claude-kit\'." -ForegroundColor Yellow
|
|
127
|
+
Write-Host " Aku tetap lanjut, tapi AGENTS.md akan rujuk path '.\$kitFolderName\'" -ForegroundColor Yellow
|
|
128
|
+
Write-Host " - kalau mau path standar, rename folder ini jadi '.claude-kit' dulu." -ForegroundColor Yellow
|
|
129
|
+
Write-Host ""
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
# ---- Resolve root proyek (parent dari folder kit) ----
|
|
133
|
+
$ProjectRoot = Split-Path -Parent $KitDir
|
|
134
|
+
$ProjectName = Split-Path -Leaf $ProjectRoot
|
|
135
|
+
$Today = Get-Date -Format 'yyyy-MM-dd'
|
|
136
|
+
$Timestamp = Get-Date -Format 'yyyyMMdd-HHmmss'
|
|
137
|
+
|
|
138
|
+
# ---- Init manifest state (lib\manifest.ps1) ----
|
|
139
|
+
$manifestState = Initialize-Manifest -ProjectRoot $ProjectRoot
|
|
140
|
+
|
|
141
|
+
# ---- Resolve label versi kit dari CHANGELOG.md (lib\version-detect.ps1) ----
|
|
142
|
+
$kitChangelog = Join-Path $KitDir 'CHANGELOG.md'
|
|
143
|
+
$detectedVersion = Get-KitVersionFromChangelog -ChangelogPath $kitChangelog
|
|
144
|
+
$KitVersion = if ($detectedVersion) { $detectedVersion } else { 'pre-launch (testing)' }
|
|
145
|
+
|
|
146
|
+
# ---- Validasi: root proyek terlihat valid ----
|
|
147
|
+
if (-not (Test-Path $ProjectRoot)) {
|
|
148
|
+
Write-Host "ERROR: Root proyek tidak ditemukan: $ProjectRoot" -ForegroundColor Red
|
|
149
|
+
Write-Host " Pastikan folder kit ini ada di dalam folder proyek." -ForegroundColor Red
|
|
150
|
+
exit 1
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
# ---- Strip .claude-kit/.git/ (lib\git-helpers.ps1) ----
|
|
154
|
+
# Saat kit di-clone (bukan zip-extract), folder .git/ ikut ke project. Bersihkan
|
|
155
|
+
# SEKALI di awal setup. Idempotent: skip kalau folder tidak ada.
|
|
156
|
+
if (-not $DryRun) {
|
|
157
|
+
$gitOk = Remove-GitMetadata -Path $KitDir
|
|
158
|
+
if ($gitOk) {
|
|
159
|
+
# Only print success kalau folder memang sempat ada (Remove-GitMetadata
|
|
160
|
+
# return $true juga untuk no-op). Cek silent: kalau .git masih ada = gagal.
|
|
161
|
+
if (-not (Test-Path -LiteralPath (Join-Path $KitDir '.git'))) {
|
|
162
|
+
# Silent kalau no-op (cleaner output); kit-clone case akan log via Write-Verbose.
|
|
163
|
+
}
|
|
164
|
+
} else {
|
|
165
|
+
Write-Host "WARN Gagal hapus .claude-kit\.git\ (lihat Write-Warning di atas)" -ForegroundColor Yellow
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
# ---- Mark-of-the-Web unblock (lib\git-helpers.ps1) ----
|
|
170
|
+
if (-not $DryRun) {
|
|
171
|
+
$motwOk = Remove-MotwBlock -Path $KitDir
|
|
172
|
+
if ($motwOk) {
|
|
173
|
+
Write-Host "OK Mark-of-the-Web di-unblock untuk semua file kit." -ForegroundColor Green
|
|
174
|
+
} else {
|
|
175
|
+
Write-Host "PERINGATAN: Unblock-File gagal (script tetap lanjut, mungkin perlu Unblock-File manual)" -ForegroundColor Yellow
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
# ---- Deteksi CLAUDE.md existing (proyek setengah jadi mungkin punya aturan custom) ----
|
|
180
|
+
$claudeMdPath = Join-Path $ProjectRoot 'CLAUDE.md'
|
|
181
|
+
if (Test-Path $claudeMdPath) {
|
|
182
|
+
Write-Host ""
|
|
183
|
+
Write-Host "DETEKSI: CLAUDE.md sudah ada di root proyek ($claudeMdPath)." -ForegroundColor Yellow
|
|
184
|
+
Write-Host " Pola B pakai AGENTS.md (BUKAN CLAUDE.md) untuk override proyek." -ForegroundColor Yellow
|
|
185
|
+
Write-Host " Kalau punya 2 file aturan, AI bisa bingung mana yang menang."
|
|
186
|
+
if (-not $Force -and -not $DryRun) {
|
|
187
|
+
Write-Host ""
|
|
188
|
+
Write-Host "Pilih aksi:" -ForegroundColor Cyan
|
|
189
|
+
Write-Host " [1] Rename CLAUDE.md jadi CLAUDE.md.legacy-$Timestamp lalu lanjut setup"
|
|
190
|
+
Write-Host " [2] Biarkan dua-duanya (AGENTS.md proyek menang per Path resolution rule)"
|
|
191
|
+
Write-Host " [3] Batalkan setup (mau merge manual dulu)"
|
|
192
|
+
$choice = '2'
|
|
193
|
+
try {
|
|
194
|
+
$choice = Read-Host "Pilih [1/2/3]"
|
|
195
|
+
if ([string]::IsNullOrWhiteSpace($choice)) { $choice = '2' }
|
|
196
|
+
} catch {
|
|
197
|
+
Write-Host "INFO: Shell NonInteractive terdeteksi, pakai default [2] biarkan CLAUDE.md." -ForegroundColor Yellow
|
|
198
|
+
Write-Host " (Jalankan di PowerShell window kalau mau pilih [1]/[3], atau pakai -Force untuk skip prompt.)" -ForegroundColor Yellow
|
|
199
|
+
$choice = '2'
|
|
200
|
+
}
|
|
201
|
+
switch ($choice) {
|
|
202
|
+
'1' {
|
|
203
|
+
$legacyName = "$claudeMdPath.legacy-$Timestamp"
|
|
204
|
+
try {
|
|
205
|
+
Move-Item $claudeMdPath $legacyName -Force
|
|
206
|
+
Write-Host "RENAMED $claudeMdPath -> $legacyName" -ForegroundColor Green
|
|
207
|
+
} catch {
|
|
208
|
+
Write-Host "GAGAL rename CLAUDE.md: $_" -ForegroundColor Red
|
|
209
|
+
Write-Host " Kemungkinan file lagi di-open di editor (VS Code/Notepad)." -ForegroundColor Red
|
|
210
|
+
Write-Host " Tutup editor + jalankan ulang script, atau pilih opsi [2] biarkan." -ForegroundColor Red
|
|
211
|
+
exit 1
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
'3' {
|
|
215
|
+
Write-Host "Dibatalkan. Setup tidak dilanjutkan." -ForegroundColor Yellow
|
|
216
|
+
exit 0
|
|
217
|
+
}
|
|
218
|
+
default {
|
|
219
|
+
Write-Host "INFO: Membiarkan CLAUDE.md existing. AGENTS.md baru akan dibuat." -ForegroundColor Cyan
|
|
220
|
+
Write-Host " Pastikan tim paham: AGENTS.md menang untuk override per Path resolution rule." -ForegroundColor Cyan
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
} elseif ($DryRun) {
|
|
224
|
+
Write-Host "[DRY] (interactive mode bakal tanya rename/biarkan/batal - pakai -Force untuk skip prompt)" -ForegroundColor Yellow
|
|
225
|
+
}
|
|
226
|
+
Write-Host ""
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
Write-Host ""
|
|
230
|
+
Write-Host "=== Setup Pola B (kit embed di proyek) ===" -ForegroundColor Cyan
|
|
231
|
+
Write-Host "Folder kit : $KitDir"
|
|
232
|
+
Write-Host "Root proyek : $ProjectRoot"
|
|
233
|
+
Write-Host "Nama proyek : $ProjectName"
|
|
234
|
+
Write-Host "Tanggal : $Today"
|
|
235
|
+
if ($DryRun) {
|
|
236
|
+
Write-Host "Mode : DRY-RUN (tidak ada file yang ditulis)" -ForegroundColor Yellow
|
|
237
|
+
}
|
|
238
|
+
Write-Host ""
|
|
239
|
+
|
|
240
|
+
# ---- Verifikasi file inti kit ada ----
|
|
241
|
+
# Source of truth: lib\kit-files.psd1 (single manifest, di-load semua konsumen)
|
|
242
|
+
$kitFilesPsd1 = Join-Path $KitDir 'lib\kit-files.psd1'
|
|
243
|
+
if (-not (Test-Path $kitFilesPsd1)) {
|
|
244
|
+
Write-Host "ERROR: lib\kit-files.psd1 hilang. Extract ulang zip kit." -ForegroundColor Red
|
|
245
|
+
exit 1
|
|
246
|
+
}
|
|
247
|
+
$kitFiles = Import-PowerShellDataFile -Path $kitFilesPsd1
|
|
248
|
+
$wajibAda = @(
|
|
249
|
+
$kitFiles.core_prompts +
|
|
250
|
+
$kitFiles.universal_rules +
|
|
251
|
+
$kitFiles.scripts +
|
|
252
|
+
$kitFiles.lib_files +
|
|
253
|
+
$kitFiles.templates +
|
|
254
|
+
$kitFiles.docs +
|
|
255
|
+
$kitFiles.tests +
|
|
256
|
+
$kitFiles.ci +
|
|
257
|
+
$kitFiles.meta
|
|
258
|
+
) | ForEach-Object { $_ -replace '/', '\' }
|
|
259
|
+
|
|
260
|
+
$missing = @()
|
|
261
|
+
foreach ($f in $wajibAda) {
|
|
262
|
+
$p = Join-Path $KitDir $f
|
|
263
|
+
if (-not (Test-Path $p)) { $missing += $f }
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
if ($missing.Count -gt 0) {
|
|
267
|
+
Write-Host "ERROR: Kit tidak lengkap. File hilang:" -ForegroundColor Red
|
|
268
|
+
foreach ($f in $missing) { Write-Host " - $f" -ForegroundColor Red }
|
|
269
|
+
Write-Host ""
|
|
270
|
+
Write-Host " Extract ulang zip kit ke folder ini, lalu jalankan script lagi." -ForegroundColor Red
|
|
271
|
+
exit 1
|
|
272
|
+
}
|
|
273
|
+
Write-Host ("OK {0} file inti kit terverifikasi" -f $wajibAda.Count) -ForegroundColor Green
|
|
274
|
+
|
|
275
|
+
# ---- Deploy lib/ helper scripts (track ke manifest) ----
|
|
276
|
+
$libDir = Join-Path $KitDir 'lib'
|
|
277
|
+
if (-not (Test-Path $libDir)) {
|
|
278
|
+
if (-not $DryRun) {
|
|
279
|
+
New-Item -ItemType Directory -Path $libDir -Force | Out-Null
|
|
280
|
+
Add-DirToManifest -State $manifestState -DirPath $libDir
|
|
281
|
+
Write-Host "CREATED $libDir\" -ForegroundColor Green
|
|
282
|
+
} else {
|
|
283
|
+
Write-Host "[DRY] CREATE $libDir\" -ForegroundColor Yellow
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
$libFiles = @('rollback.ps1', 'safety.ps1', 'manifest-signing.ps1')
|
|
287
|
+
foreach ($lf in $libFiles) {
|
|
288
|
+
$lfPath = Join-Path $libDir $lf
|
|
289
|
+
if (Test-Path $lfPath) {
|
|
290
|
+
if (-not $DryRun) {
|
|
291
|
+
Add-ToManifest -State $manifestState -FilePath $lfPath -Kind 'lib' -From ('.claude-kit/lib/' + $lf)
|
|
292
|
+
Write-Host ("OK {0} (tracked)" -f $lfPath) -ForegroundColor Green
|
|
293
|
+
} else {
|
|
294
|
+
Write-Host ("[DRY] TRACK {0}" -f $lfPath) -ForegroundColor Yellow
|
|
295
|
+
}
|
|
296
|
+
} else {
|
|
297
|
+
Write-Host ("WARN lib file tidak ditemukan: {0} (skip track)" -f $lfPath) -ForegroundColor Yellow
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
# ---- Tanya optional info untuk fill placeholder ----
|
|
302
|
+
$ownerName = ''
|
|
303
|
+
$repoUrl = ''
|
|
304
|
+
if (-not $Force -and -not $DryRun) {
|
|
305
|
+
Write-Host ""
|
|
306
|
+
Write-Host "Optional: isi info berikut untuk pre-fill AGENTS.md (Enter = pakai default):" -ForegroundColor Cyan
|
|
307
|
+
try {
|
|
308
|
+
$ownerName = Read-Host ("Nama kamu (default: {0})" -f $env:USERNAME)
|
|
309
|
+
$repoUrl = Read-Host "URL repo standar tim (Enter = 'belum-ada')"
|
|
310
|
+
} catch {
|
|
311
|
+
Write-Host "INFO: Shell NonInteractive terdeteksi, pakai default value." -ForegroundColor Yellow
|
|
312
|
+
Write-Host " (Jalankan setup langsung di PowerShell window kalau mau isi prompt.)" -ForegroundColor Yellow
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
# Fallback default kalau kosong (skip prompt karena -Force/-DryRun, atau user tekan Enter)
|
|
316
|
+
if (-not $ownerName) { $ownerName = $env:USERNAME }
|
|
317
|
+
if (-not $repoUrl) { $repoUrl = 'belum-ada (solo project)' }
|
|
318
|
+
|
|
319
|
+
# ---- Setup AGENTS.md di root proyek (lib\agents-md.ps1) ----
|
|
320
|
+
$agentsTemplate = Join-Path $KitDir 'AGENTS.md.template'
|
|
321
|
+
$agentsTarget = Join-Path $ProjectRoot 'AGENTS.md'
|
|
322
|
+
|
|
323
|
+
# Decide preserve vs overwrite + handle interactive prompt
|
|
324
|
+
$shouldPreserve = $false
|
|
325
|
+
if (Test-Path $agentsTarget) {
|
|
326
|
+
if (-not $Force -and -not $DryRun) {
|
|
327
|
+
Write-Host ""
|
|
328
|
+
Write-Host "PERHATIAN: $agentsTarget sudah ada." -ForegroundColor Yellow
|
|
329
|
+
Write-Host " Pakai -Force untuk backup + timpa." -ForegroundColor Yellow
|
|
330
|
+
Write-Host " Atau hapus AGENTS.md existing manual, lalu jalankan script lagi." -ForegroundColor Yellow
|
|
331
|
+
$answer = 'N'
|
|
332
|
+
try {
|
|
333
|
+
$answer = Read-Host "Backup AGENTS.md existing + timpa dengan template baru? (Y/N)"
|
|
334
|
+
} catch {
|
|
335
|
+
Write-Host "INFO: Shell NonInteractive terdeteksi. AGENTS.md existing dipertahankan (default safe)." -ForegroundColor Yellow
|
|
336
|
+
Write-Host " Pakai -Force kalau memang mau timpa, atau jalankan di PowerShell window." -ForegroundColor Yellow
|
|
337
|
+
$answer = 'N'
|
|
338
|
+
}
|
|
339
|
+
if ($answer -notmatch '^[Yy]') {
|
|
340
|
+
Write-Host "Dibatalkan oleh user. AGENTS.md existing tidak diubah." -ForegroundColor Yellow
|
|
341
|
+
Write-Host "Setup tetap OK - kit di .claude-kit\ siap dipakai." -ForegroundColor Green
|
|
342
|
+
exit 0
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
# Build placeholder set (shared dengan docs/ templates di bawah)
|
|
348
|
+
$agentsPlaceholders = @{
|
|
349
|
+
'<NAMA_PROYEK>' = $ProjectName
|
|
350
|
+
'<TANGGAL_HARI_INI>' = $Today
|
|
351
|
+
'<NAMA_KAMU>' = $ownerName
|
|
352
|
+
'<URL_REPO_STANDAR>' = $repoUrl
|
|
353
|
+
'<VERSI_KIT>' = $KitVersion
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
if ($DryRun) {
|
|
357
|
+
Write-Host "[DRY] DEPLOY AGENTS.md (template fill + backup kalau existing)" -ForegroundColor Yellow
|
|
358
|
+
Write-Host "[DRY] Placeholders: NAMA_PROYEK='$ProjectName', TANGGAL_HARI_INI='$Today', VERSI_KIT='$KitVersion'" -ForegroundColor Yellow
|
|
359
|
+
} else {
|
|
360
|
+
try {
|
|
361
|
+
$deployResult = Deploy-AgentsMd `
|
|
362
|
+
-ProjectRoot $ProjectRoot `
|
|
363
|
+
-TemplatePath $agentsTemplate `
|
|
364
|
+
-Placeholders $agentsPlaceholders
|
|
365
|
+
# Track backup ke manifest kalau ada
|
|
366
|
+
if ($deployResult.backup_path) {
|
|
367
|
+
Add-ToManifest -State $manifestState -FilePath $deployResult.backup_path -Kind 'backup' -From 'AGENTS.md (pre-Force backup)'
|
|
368
|
+
Write-Host "BACKUP $agentsTarget -> $($deployResult.backup_path)" -ForegroundColor Yellow
|
|
369
|
+
}
|
|
370
|
+
Add-ToManifest -State $manifestState -FilePath $deployResult.target_path -Kind 'filled_template' -From 'AGENTS.md.template'
|
|
371
|
+
Write-Host "OK $($deployResult.target_path)" -ForegroundColor Green
|
|
372
|
+
$filled = "NAMA_PROYEK='$ProjectName', TANGGAL_HARI_INI='$Today', NAMA_KAMU='$ownerName', URL_REPO_STANDAR='$repoUrl', VERSI_KIT='$KitVersion'"
|
|
373
|
+
Write-Host " Pre-filled: $filled" -ForegroundColor Green
|
|
374
|
+
} catch {
|
|
375
|
+
Write-Host "GAGAL deploy AGENTS.md: $_" -ForegroundColor Red
|
|
376
|
+
exit 1
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
# ---- Bootstrap docs/ skeleton ----
|
|
381
|
+
$docsDir = Join-Path $ProjectRoot 'docs'
|
|
382
|
+
|
|
383
|
+
# Sanity check: proyek hampir kosong? Skip docs/ skeleton supaya tidak prematur.
|
|
384
|
+
$excludeNames = @(
|
|
385
|
+
'.git', '.claude-kit', 'AGENTS.md', 'docs',
|
|
386
|
+
'node_modules', 'vendor', 'dist', 'build', 'out', 'target',
|
|
387
|
+
'__pycache__', '.venv', 'venv', '.next', '.nuxt', '.turbo', '.cache'
|
|
388
|
+
)
|
|
389
|
+
$nonHiddenFiles = @(Get-ChildItem -Path $ProjectRoot -Force -ErrorAction SilentlyContinue | Where-Object {
|
|
390
|
+
$_.Name -notin $excludeNames -and -not $_.Name.StartsWith('.')
|
|
391
|
+
})
|
|
392
|
+
$proyekHampirKosong = ($nonHiddenFiles.Count -le 1)
|
|
393
|
+
|
|
394
|
+
if ($proyekHampirKosong) {
|
|
395
|
+
Write-Host ""
|
|
396
|
+
Write-Host "INFO: Proyek terlihat hampir kosong - skip docs/ skeleton (terlalu prematur)." -ForegroundColor Cyan
|
|
397
|
+
Write-Host " Setelah ada code, jalankan ulang AI dengan prompt PROJECT_LIFECYCLE_PROMPT_v1.md (Stage B: Bootstrap Docs)" -ForegroundColor Cyan
|
|
398
|
+
} else {
|
|
399
|
+
if (-not (Test-Path $docsDir)) {
|
|
400
|
+
if (-not $DryRun) {
|
|
401
|
+
New-Item -ItemType Directory -Path $docsDir -Force | Out-Null
|
|
402
|
+
Add-DirToManifest -State $manifestState -DirPath $docsDir
|
|
403
|
+
Write-Host ""
|
|
404
|
+
Write-Host "CREATED $docsDir\" -ForegroundColor Green
|
|
405
|
+
} else {
|
|
406
|
+
Write-Host "[DRY] CREATE $docsDir\" -ForegroundColor Yellow
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
# Templates dengan placeholder substitution
|
|
411
|
+
$docsTemplatesWithPlaceholder = @(
|
|
412
|
+
@{ Src = 'templates\architecture.md'; Dst = (Join-Path $docsDir 'architecture.md'); From = 'templates/architecture.md'; Placeholders = @{
|
|
413
|
+
'<NAMA_PROYEK>' = $ProjectName
|
|
414
|
+
'[TBD: tanggal hari ini, format YYYY-MM-DD]' = $Today
|
|
415
|
+
'[TBD: YYYY-MM-DD]' = $Today
|
|
416
|
+
}},
|
|
417
|
+
@{ Src = 'templates\glossary.md'; Dst = (Join-Path $docsDir 'glossary.md'); From = 'templates/glossary.md'; Placeholders = @{
|
|
418
|
+
'<NAMA_PROYEK>' = $ProjectName
|
|
419
|
+
'<YYYY-MM-DD>' = $Today
|
|
420
|
+
}}
|
|
421
|
+
)
|
|
422
|
+
foreach ($t in $docsTemplatesWithPlaceholder) {
|
|
423
|
+
$tSrc = Join-Path $KitDir $t.Src
|
|
424
|
+
$tDst = $t.Dst
|
|
425
|
+
if (Test-Path $tDst) {
|
|
426
|
+
Write-Host "SKIP $tDst (sudah ada, tidak di-overwrite)" -ForegroundColor Yellow
|
|
427
|
+
} elseif (-not (Test-Path $tSrc)) {
|
|
428
|
+
Write-Host ("WARN Template tidak ditemukan: {0} (skip)" -f $tSrc) -ForegroundColor Yellow
|
|
429
|
+
} elseif (-not $DryRun) {
|
|
430
|
+
$r = Copy-TemplateWithPlaceholder -SourcePath $tSrc -TargetPath $tDst -Placeholders $t.Placeholders -IfExists 'Skip'
|
|
431
|
+
if ($r.copied) {
|
|
432
|
+
Add-ToManifest -State $manifestState -FilePath $tDst -Kind 'skeleton' -From $t.From
|
|
433
|
+
Write-Host ("OK {0} (skeleton, pre-filled NAMA_PROYEK='{1}')" -f $tDst, $ProjectName) -ForegroundColor Green
|
|
434
|
+
} elseif ($r.action -eq 'missing') {
|
|
435
|
+
Write-Host ("GAGAL copy {0}: source missing" -f $t.Dst) -ForegroundColor Red
|
|
436
|
+
}
|
|
437
|
+
} else {
|
|
438
|
+
Write-Host "[DRY] COPY $tSrc -> $tDst" -ForegroundColor Yellow
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
# 3 file template tambahan (tanpa placeholder substitution, plain copy)
|
|
443
|
+
$extraTemplates = @(
|
|
444
|
+
@{ TemplateName = '_PATTERNS.md'; TargetName = '_PATTERNS.md'; Desc = 'aturan dokumentasi tim profesional generic' },
|
|
445
|
+
@{ TemplateName = '_EXAMPLE.md'; TargetName = '_EXAMPLE.md'; Desc = 'contoh format .md pendamping siap-copy' },
|
|
446
|
+
@{ TemplateName = 'architecture_auto.md'; TargetName = 'architecture_auto.md'; Desc = 'registry TOC AI-maintained skeleton' }
|
|
447
|
+
)
|
|
448
|
+
foreach ($t in $extraTemplates) {
|
|
449
|
+
$tSrc = Join-Path $KitDir ('templates\' + $t.TemplateName)
|
|
450
|
+
$tDst = Join-Path $docsDir $t.TargetName
|
|
451
|
+
if (Test-Path $tDst) {
|
|
452
|
+
Write-Host "SKIP $tDst (sudah ada, tidak di-overwrite)" -ForegroundColor Yellow
|
|
453
|
+
} elseif (-not (Test-Path $tSrc)) {
|
|
454
|
+
Write-Host ("WARN Template tidak ditemukan: {0} (skip)" -f $tSrc) -ForegroundColor Yellow
|
|
455
|
+
} elseif (-not $DryRun) {
|
|
456
|
+
$r = Copy-StaticTemplate -SourcePath $tSrc -TargetPath $tDst -IfExists 'Skip'
|
|
457
|
+
if ($r.copied) {
|
|
458
|
+
Add-ToManifest -State $manifestState -FilePath $tDst -Kind 'skeleton' -From ('templates/' + $t.TemplateName)
|
|
459
|
+
Write-Host ("OK {0} ({1})" -f $tDst, $t.Desc) -ForegroundColor Green
|
|
460
|
+
} elseif ($r.action -eq 'missing') {
|
|
461
|
+
Write-Host ("GAGAL copy {0}: source missing" -f $t.TargetName) -ForegroundColor Red
|
|
462
|
+
}
|
|
463
|
+
} else {
|
|
464
|
+
Write-Host "[DRY] COPY $tSrc -> $tDst" -ForegroundColor Yellow
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
# ---- Bootstrap TIM files (Team Mode T = default) ----
|
|
470
|
+
if (-not $SkipTeamFiles -and -not $proyekHampirKosong) {
|
|
471
|
+
Write-Host ""
|
|
472
|
+
Write-Host "=== Copy file tim (Team Mode) ===" -ForegroundColor Cyan
|
|
473
|
+
|
|
474
|
+
# Buat folder .github/ + workflows + scripts kalau belum ada
|
|
475
|
+
$githubDir = Join-Path $ProjectRoot '.github'
|
|
476
|
+
$workflowsDir = Join-Path $githubDir 'workflows'
|
|
477
|
+
$scriptsDir = Join-Path $githubDir 'scripts'
|
|
478
|
+
foreach ($d in @($githubDir, $workflowsDir, $scriptsDir)) {
|
|
479
|
+
if (-not (Test-Path $d) -and -not $DryRun) {
|
|
480
|
+
New-Item -ItemType Directory -Path $d -Force | Out-Null
|
|
481
|
+
Add-DirToManifest -State $manifestState -DirPath $d
|
|
482
|
+
Write-Host ("CREATED {0}\" -f $d) -ForegroundColor Green
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
# Buat folder docs/decisions/ kalau belum ada
|
|
487
|
+
$decisionsDir = Join-Path $docsDir 'decisions'
|
|
488
|
+
if (-not (Test-Path $decisionsDir) -and -not $DryRun) {
|
|
489
|
+
New-Item -ItemType Directory -Path $decisionsDir -Force | Out-Null
|
|
490
|
+
Add-DirToManifest -State $manifestState -DirPath $decisionsDir
|
|
491
|
+
Write-Host ("CREATED {0}\" -f $decisionsDir) -ForegroundColor Green
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
# Mapping file tim: src (di .claude-kit) -> dst (di project root)
|
|
495
|
+
$teamFiles = @(
|
|
496
|
+
@{ Src = 'templates\github\workflows\ai-review.yml'; Dst = (Join-Path $workflowsDir 'ai-review.yml'); Desc = 'GitHub Action Senior AI Reviewer' },
|
|
497
|
+
@{ Src = 'templates\github\workflows\backup-schemas.yml'; Dst = (Join-Path $workflowsDir 'backup-schemas.yml'); Desc = 'GitHub Action daily backup pg_dump per-schema (L3 backup)' },
|
|
498
|
+
@{ Src = 'templates\github\scripts\ai-review.js'; Dst = (Join-Path $scriptsDir 'ai-review.js'); Desc = 'Script Senior AI Reviewer' },
|
|
499
|
+
@{ Src = 'templates\github\CODEOWNERS.template'; Dst = (Join-Path $githubDir 'CODEOWNERS'); Desc = 'CODEOWNERS template (WAJIB edit dengan username actual)' },
|
|
500
|
+
@{ Src = 'templates\github\pull_request_template.md'; Dst = (Join-Path $githubDir 'pull_request_template.md'); Desc = 'PR template tim' },
|
|
501
|
+
@{ Src = 'templates\CLAUDE_TEAM_GUIDE.md'; Dst = (Join-Path $docsDir 'CLAUDE_TEAM_GUIDE.md'); Desc = 'Panduan tim AI-first' },
|
|
502
|
+
@{ Src = 'templates\PROMPT_LIBRARY.md'; Dst = (Join-Path $docsDir 'PROMPT_LIBRARY.md'); Desc = '15 prompt pattern siap-pakai (1-10 generic + 11-15 chat-driven)' },
|
|
503
|
+
@{ Src = 'templates\ONBOARDING.md'; Dst = (Join-Path $docsDir 'ONBOARDING.md'); Desc = 'Playbook dev baru' },
|
|
504
|
+
@{ Src = 'templates\STACK_GUIDE.md'; Dst = (Join-Path $docsDir 'STACK_GUIDE.md'); Desc = 'Next.js + Vercel + SEO + security' },
|
|
505
|
+
@{ Src = 'templates\STACK_MIGRATION_GUIDE.md'; Dst = (Join-Path $docsDir 'STACK_MIGRATION_GUIDE.md'); Desc = 'Migrasi Vercel -> Railway/Render (ADVANCED post-launch)' },
|
|
506
|
+
@{ Src = 'templates\MCP_SETUP.md'; Dst = (Join-Path $docsDir 'MCP_SETUP.md'); Desc = 'MCP setup + Decision Tree Postgres/Supabase' },
|
|
507
|
+
@{ Src = 'templates\RLS_SETUP_PROMPT.md'; Dst = (Join-Path $docsDir 'RLS_SETUP_PROMPT.md'); Desc = 'RLS setup prompt untuk staff IT schema-scoped' },
|
|
508
|
+
@{ Src = 'templates\DB_SCHEMA_SCAN_PROMPT.md'; Dst = (Join-Path $docsDir 'DB_SCHEMA_SCAN_PROMPT.md'); Desc = 'Scan DB schema -> docs/db-schema.md' },
|
|
509
|
+
@{ Src = 'templates\GLOSSARY_NON_PROGRAMMER.md'; Dst = (Join-Path $docsDir 'GLOSSARY_NON_PROGRAMMER.md'); Desc = 'Glossary istilah teknis untuk non-programmer (WAJIB baca dulu)' },
|
|
510
|
+
@{ Src = 'templates\ANALOGI_LIBRARY.md'; Dst = (Join-Path $docsDir 'ANALOGI_LIBRARY.md'); Desc = '30 jargon teknis x 3-layer analogi tools digital populer Indonesia (cadangan rujukan AI)' },
|
|
511
|
+
@{ Src = 'templates\UPDATE_GUIDE.md'; Dst = (Join-Path $docsDir 'UPDATE_GUIDE.md'); Desc = 'Panduan staff IT non-programmer cara update kit (4-tier strategy + analogi tools digital)' },
|
|
512
|
+
@{ Src = 'templates\SECURITY_INCIDENT_PLAYBOOK.md'; Dst = (Join-Path $docsDir 'SECURITY_INCIDENT_PLAYBOOK.md'); Desc = 'Security incident playbook (kalau token bocor / data leak)' },
|
|
513
|
+
@{ Src = 'templates\feature-flags-advanced.md'; Dst = (Join-Path $docsDir 'feature-flags-advanced.md'); Desc = 'Feature flag pattern (ADVANCED, post-launch only)' },
|
|
514
|
+
@{ Src = 'templates\decisions\_TEMPLATE.md'; Dst = (Join-Path $decisionsDir '_TEMPLATE.md'); Desc = 'ADR template' },
|
|
515
|
+
@{ Src = 'templates\decisions\README.md'; Dst = (Join-Path $decisionsDir 'README.md'); Desc = 'ADR folder README' }
|
|
516
|
+
)
|
|
517
|
+
|
|
518
|
+
foreach ($t in $teamFiles) {
|
|
519
|
+
$tSrc = Join-Path $KitDir $t.Src
|
|
520
|
+
$tDst = $t.Dst
|
|
521
|
+
if (Test-Path $tDst) {
|
|
522
|
+
Write-Host ("SKIP {0} (sudah ada, tidak di-overwrite)" -f $tDst) -ForegroundColor Yellow
|
|
523
|
+
} elseif (-not (Test-Path $tSrc)) {
|
|
524
|
+
Write-Host ("WARN File tim tidak ditemukan di kit: {0} (skip)" -f $tSrc) -ForegroundColor Yellow
|
|
525
|
+
} elseif (-not $DryRun) {
|
|
526
|
+
$r = Copy-StaticTemplate -SourcePath $tSrc -TargetPath $tDst -IfExists 'Skip'
|
|
527
|
+
if ($r.copied) {
|
|
528
|
+
# Pakai forward slash di field 'from' supaya konsisten cross-platform di JSON
|
|
529
|
+
$fromRel = $t.Src.Replace('\','/')
|
|
530
|
+
Add-ToManifest -State $manifestState -FilePath $tDst -Kind 'team_file' -From $fromRel
|
|
531
|
+
Write-Host ("OK {0} ({1})" -f $tDst, $t.Desc) -ForegroundColor Green
|
|
532
|
+
} elseif ($r.action -eq 'missing') {
|
|
533
|
+
Write-Host ("GAGAL copy {0}: source missing" -f $t.Src) -ForegroundColor Red
|
|
534
|
+
}
|
|
535
|
+
} else {
|
|
536
|
+
Write-Host "[DRY] COPY $tSrc -> $tDst" -ForegroundColor Yellow
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
# Copy docs/SIGNED_RELEASE.md (sourced dari kit's docs/ folder, bukan templates/)
|
|
541
|
+
$signedReleaseSrc = Join-Path $KitDir 'docs\SIGNED_RELEASE.md'
|
|
542
|
+
$signedReleaseDst = Join-Path $docsDir 'SIGNED_RELEASE.md'
|
|
543
|
+
if (Test-Path $signedReleaseDst) {
|
|
544
|
+
Write-Host ("SKIP {0} (sudah ada, tidak di-overwrite)" -f $signedReleaseDst) -ForegroundColor Yellow
|
|
545
|
+
} elseif (-not (Test-Path $signedReleaseSrc)) {
|
|
546
|
+
Write-Host ("WARN docs/SIGNED_RELEASE.md tidak ditemukan di kit: {0} (skip)" -f $signedReleaseSrc) -ForegroundColor Yellow
|
|
547
|
+
} elseif (-not $DryRun) {
|
|
548
|
+
# Pastikan docs/ ada (edge case kalau heuristic skip creation tapi user disable -SkipTeamFiles)
|
|
549
|
+
if (-not (Test-Path $docsDir)) {
|
|
550
|
+
New-Item -ItemType Directory -Path $docsDir -Force | Out-Null
|
|
551
|
+
Add-DirToManifest -State $manifestState -DirPath $docsDir
|
|
552
|
+
}
|
|
553
|
+
$r = Copy-StaticTemplate -SourcePath $signedReleaseSrc -TargetPath $signedReleaseDst -IfExists 'Skip'
|
|
554
|
+
if ($r.copied) {
|
|
555
|
+
Add-ToManifest -State $manifestState -FilePath $signedReleaseDst -Kind 'team_file' -From 'docs/SIGNED_RELEASE.md'
|
|
556
|
+
Write-Host ("OK {0} (panduan verifikasi signed release)" -f $signedReleaseDst) -ForegroundColor Green
|
|
557
|
+
}
|
|
558
|
+
} else {
|
|
559
|
+
Write-Host "[DRY] COPY $signedReleaseSrc -> $signedReleaseDst" -ForegroundColor Yellow
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
Write-Host ""
|
|
563
|
+
Write-Host "REMINDER untuk Team Mode:" -ForegroundColor Cyan
|
|
564
|
+
Write-Host " 1. Edit .github\CODEOWNERS - ganti placeholder dengan GitHub username actual."
|
|
565
|
+
Write-Host " 2. Setup ANTHROPIC_API_KEY di GitHub repo Settings -> Secrets -> Actions."
|
|
566
|
+
Write-Host " 3. Baca docs\CLAUDE_TEAM_GUIDE.md (panduan tim) + docs\PROMPT_LIBRARY.md."
|
|
567
|
+
Write-Host " 4. Kalau pakai DB: setup schema isolation + RLS:"
|
|
568
|
+
Write-Host " - docs\MCP_SETUP.md (PostgreSQL MCP default, Supabase MCP owner-only)"
|
|
569
|
+
Write-Host " - docs\RLS_SETUP_PROMPT.md (paste prompt RLS untuk staff IT)"
|
|
570
|
+
Write-Host " - docs\DB_SCHEMA_SCAN_PROMPT.md (paste prompt scan schema -> docs\db-schema.md)"
|
|
571
|
+
} elseif ($SkipTeamFiles) {
|
|
572
|
+
Write-Host ""
|
|
573
|
+
Write-Host "INFO: -SkipTeamFiles aktif (advanced escape hatch) - skip copy .github/ + docs tim." -ForegroundColor Cyan
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
# ---- Save install manifest (lib\manifest.ps1 — merge + HMAC sign + write JSON) ----
|
|
577
|
+
if (-not $DryRun) {
|
|
578
|
+
try {
|
|
579
|
+
$saveResult = Save-Manifest `
|
|
580
|
+
-State $manifestState `
|
|
581
|
+
-KitDir $KitDir `
|
|
582
|
+
-KitVersion $KitVersion `
|
|
583
|
+
-ProjectName $ProjectName
|
|
584
|
+
|
|
585
|
+
# ---- Ensure .claude-kit/.gitignore ignore manifest + backup files ----
|
|
586
|
+
# APPEND-if-missing pattern: preserve existing .gitignore, tambah entries yang belum ada.
|
|
587
|
+
$gitignorePath = Join-Path $KitDir '.gitignore'
|
|
588
|
+
$requiredEntries = @(
|
|
589
|
+
'.install-manifest.json',
|
|
590
|
+
'*.bak',
|
|
591
|
+
'*.backup-*',
|
|
592
|
+
'*.env',
|
|
593
|
+
'*.env.local',
|
|
594
|
+
'*.pem',
|
|
595
|
+
'*.key'
|
|
596
|
+
)
|
|
597
|
+
$existingLines = @()
|
|
598
|
+
if (Test-Path -LiteralPath $gitignorePath) {
|
|
599
|
+
$existingLines = @(Get-Content -LiteralPath $gitignorePath -Encoding UTF8 -ErrorAction SilentlyContinue)
|
|
600
|
+
}
|
|
601
|
+
$missingEntries = @($requiredEntries | Where-Object { $existingLines -notcontains $_ })
|
|
602
|
+
if ($missingEntries.Count -gt 0) {
|
|
603
|
+
$appendBlock = "`n# Auto-appended oleh setup-pola-b.ps1 (lintasAI safe-uninstall hardening):`n# Cegah leak environment metadata + secret kalau user run ``git add .claude-kit/``.`n"
|
|
604
|
+
$appendBlock += ($missingEntries -join "`n") + "`n"
|
|
605
|
+
if ($existingLines.Count -gt 0) {
|
|
606
|
+
[System.IO.File]::AppendAllText($gitignorePath, $appendBlock, (New-Object System.Text.UTF8Encoding $false))
|
|
607
|
+
} else {
|
|
608
|
+
[System.IO.File]::WriteAllText($gitignorePath, $appendBlock.TrimStart("`n"), (New-Object System.Text.UTF8Encoding $false))
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
|
|
612
|
+
Write-Host ""
|
|
613
|
+
Write-Host ("OK .install-manifest.json written ({0} file + {1} dir tracked)" -f $saveResult.FilesCount, $saveResult.DirsCount) -ForegroundColor Green
|
|
614
|
+
if ($saveResult.Merged) {
|
|
615
|
+
Write-Host " Merged dengan manifest sebelumnya (re-run setup detected)." -ForegroundColor DarkGray
|
|
616
|
+
}
|
|
617
|
+
if ($saveResult.Signed) {
|
|
618
|
+
Write-Host " HMAC-signed (tamper-detection aktif)." -ForegroundColor DarkGray
|
|
619
|
+
}
|
|
620
|
+
Write-Host " Dipakai uninstall.ps1 untuk safe delete (hash-based pristine detection)." -ForegroundColor DarkGray
|
|
621
|
+
Write-Host " Anonymized: project_root='<PROJECT_ROOT>', installed_by='<USER>' (tidak leak env)." -ForegroundColor DarkGray
|
|
622
|
+
} catch {
|
|
623
|
+
Write-Host "WARN Gagal tulis .install-manifest.json: $_" -ForegroundColor Yellow
|
|
624
|
+
Write-Host " Setup TETAP berhasil, tapi uninstall.ps1 nanti minta fallback manual." -ForegroundColor Yellow
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
# ---- Ringkasan akhir (structured + actionable) ----
|
|
629
|
+
Write-Host ""
|
|
630
|
+
Write-Host "================================================================" -ForegroundColor Green
|
|
631
|
+
Write-Host (" OK KIT lintasAI - TER-INSTALL DI {0}" -f $ProjectName) -ForegroundColor Green
|
|
632
|
+
Write-Host "================================================================" -ForegroundColor Green
|
|
633
|
+
Write-Host ""
|
|
634
|
+
|
|
635
|
+
Write-Host "SUDAH AKTIF (auto-load tiap sesi AI):" -ForegroundColor Cyan
|
|
636
|
+
Write-Host " [x] Aturan AI : 4 rule docs + Tinjauan Multi-Divisi (12 divisi)"
|
|
637
|
+
if ($proyekHampirKosong) {
|
|
638
|
+
Write-Host " [ ] docs/ : SKIP (proyek hampir kosong) - akan auto-generate saat ada code"
|
|
639
|
+
Write-Host " [ ] .github/ : SKIP (proyek hampir kosong) - team files belum di-copy"
|
|
640
|
+
} else {
|
|
641
|
+
Write-Host " [x] docs/ : skeleton + panduan tim (architecture, glossary, _PATTERNS, dst.)"
|
|
642
|
+
if (-not $SkipTeamFiles) {
|
|
643
|
+
Write-Host " [x] .github/ : ai-review.yml + CODEOWNERS + PR template"
|
|
644
|
+
} else {
|
|
645
|
+
Write-Host " [ ] .github/ : SKIP (-SkipTeamFiles aktif)"
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
Write-Host " [x] Path resolution : ~/.claude/ -> .claude-kit/"
|
|
649
|
+
Write-Host ""
|
|
650
|
+
|
|
651
|
+
Write-Host "ACTION ITEMS - PERLU KAMU LAKUKAN MANUAL:" -ForegroundColor Yellow
|
|
652
|
+
$itemIdx = 1
|
|
653
|
+
if (-not $SkipTeamFiles -and -not $proyekHampirKosong) {
|
|
654
|
+
Write-Host (" [ ] ({0}) ~5 menit Edit .github/CODEOWNERS - ganti placeholder @username dengan GitHub username actual." -f $itemIdx)
|
|
655
|
+
$itemIdx++
|
|
656
|
+
Write-Host (" [ ] ({0}) ~2 menit Setup ANTHROPIC_API_KEY di GitHub: Settings -> Secrets and variables -> Actions -> New secret." -f $itemIdx)
|
|
657
|
+
$itemIdx++
|
|
658
|
+
}
|
|
659
|
+
Write-Host (" [ ] ({0}) opsional Baca docs/CLAUDE_TEAM_GUIDE.md (panduan tim) + docs/PROMPT_LIBRARY.md." -f $itemIdx)
|
|
660
|
+
$itemIdx++
|
|
661
|
+
Write-Host (" [ ] ({0}) opsional Commit setup ke git: git add AGENTS.md .claude-kit/ docs/ .github/ && git commit -m 'chore: setup standar tim IT'" -f $itemIdx)
|
|
662
|
+
Write-Host ""
|
|
663
|
+
|
|
664
|
+
Write-Host "LANGKAH SELANJUTNYA - 1 PERINTAH:" -ForegroundColor Cyan
|
|
665
|
+
Write-Host (" Buka Claude Code di {0}, paste isi:" -f $ProjectRoot)
|
|
666
|
+
Write-Host (" {0}\JALANKAN_KIT.md" -f $KitDir) -ForegroundColor Green
|
|
667
|
+
Write-Host ""
|
|
668
|
+
Write-Host " AI akan otomatis pandu kamu lewat 3 interactive popup:" -ForegroundColor Cyan
|
|
669
|
+
Write-Host " 1. Team Mode? (T) scan + bulk-bootstrap / (skip) langsung kerja"
|
|
670
|
+
Write-Host " 2. Bulk-bootstrap? (1) all / (2) per kategori / (3) skeleton-first -- kalau pilih T"
|
|
671
|
+
Write-Host " 3. Skenario? (a) proyek baru / (c) proyek setengah jadi / (d) langsung ngoding"
|
|
672
|
+
Write-Host ""
|
|
673
|
+
Write-Host " Default tiap popup (kosong/Enter): T -> 1 -> d (owner-grade full docs)" -ForegroundColor Green
|
|
674
|
+
Write-Host ""
|
|
675
|
+
Write-Host " Alternatif (skip JALANKAN_KIT): langsung ngoding aja - aturan AI tetap auto-load tiap"
|
|
676
|
+
Write-Host " sesi, LAZY-GENERATE aktif saat sentuh code CRITICAL."
|
|
677
|
+
Write-Host ""
|
|
678
|
+
Write-Host "UPDATE KIT KE VERSI BARU:" -ForegroundColor Cyan
|
|
679
|
+
Write-Host " .\.claude-kit\update-kit.ps1 (auto re-clone + backup + detect [BREAKING]/[SCAN-REQUIRED])"
|
|
680
|
+
Write-Host ""
|
|
681
|
+
|
|
682
|
+
if ($DryRun) {
|
|
683
|
+
Write-Host "Mode DRY-RUN: jalankan ulang tanpa -DryRun untuk eksekusi sungguhan." -ForegroundColor Yellow
|
|
684
|
+
}
|
|
685
|
+
Write-Host "Status: SIAP NGODING" -ForegroundColor Green
|
|
686
|
+
Write-Host ""
|
|
687
|
+
exit 0
|