@ulpi/cli 0.1.4 → 0.1.6

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 (112) hide show
  1. package/LICENSE +21 -0
  2. package/dist/{auth-PN7TMQHV-2W4ICG64.js → auth-FWM7MM4Q-VZC3U2XZ.js} +1 -1
  3. package/dist/{auth-ECQ3IB4E.js → auth-HDK7ECJL.js} +2 -1
  4. package/dist/{chunk-3SBPZRB5.js → chunk-3BCW6ABU.js} +402 -142
  5. package/dist/{chunk-JGBXM5NC.js → chunk-3WB5CXH4.js} +180 -5
  6. package/dist/{chunk-2HEE5OKX.js → chunk-4UCJIAOU.js} +2 -2
  7. package/dist/chunk-4XTHZVDS.js +109 -0
  8. package/dist/chunk-4ZPOZULQ.js +6522 -0
  9. package/dist/{chunk-SIAQVRKG.js → chunk-5MI5GIXM.js} +48 -2
  10. package/dist/{chunk-KLEASXUR.js → chunk-6ZL6NXMV.js} +1 -1
  11. package/dist/chunk-76D3BYJD.js +221 -0
  12. package/dist/{chunk-ZLYRPD7I.js → chunk-AWOSRA5F.js} +1 -1
  13. package/dist/{chunk-PDR55ZNW.js → chunk-BFEKZZHM.js} +274 -57
  14. package/dist/chunk-C7CLUQI6.js +1286 -0
  15. package/dist/{chunk-7AL4DOEJ.js → chunk-E3B5NROU.js} +7 -7
  16. package/dist/chunk-EJ7TW77N.js +1418 -0
  17. package/dist/{chunk-5J6NLQUN.js → chunk-IV6MWETF.js} +383 -168
  18. package/dist/chunk-IZPJHSPX.js +1478 -0
  19. package/dist/chunk-JLHNLM3C.js +228 -0
  20. package/dist/{chunk-BZL5H4YQ.js → chunk-KYYI23AQ.js} +2 -2
  21. package/dist/{chunk-2CLNOKPA.js → chunk-RSFJ6QSR.js} +18 -0
  22. package/dist/chunk-S6ANCSYO.js +1271 -0
  23. package/dist/chunk-SEU7WWNQ.js +1251 -0
  24. package/dist/chunk-SNQ7NAIS.js +453 -0
  25. package/dist/{ulpi-RMMCUAGP-JCJ273T6.js → chunk-TSLDGT5O.js} +73 -35
  26. package/dist/{chunk-SPOI23SB.js → chunk-UXHCHOWQ.js} +83 -62
  27. package/dist/chunk-V2H5D6Y3.js +146 -0
  28. package/dist/{chunk-QJ5GSMEC.js → chunk-VVEDXI7E.js} +2 -1
  29. package/dist/chunk-VXH5Y4FO.js +6761 -0
  30. package/dist/chunk-WED4LM5N.js +322 -0
  31. package/dist/{chunk-74WVVWJ4.js → chunk-YOKL7RB5.js} +184 -15
  32. package/dist/chunk-Z53CAR7G.js +298 -0
  33. package/dist/ci-X3U2W4HC.js +854 -0
  34. package/dist/cloud-2F3NLVHN.js +274 -0
  35. package/dist/{codemap-RKSD4MIE.js → codemap-XNGMAF3F.js} +37 -37
  36. package/dist/codex-MB5YTMRT.js +132 -0
  37. package/dist/{config-EGAXXCGL.js → config-OOELBYTH.js} +1 -1
  38. package/dist/dist-2BJYR5EI.js +59 -0
  39. package/dist/dist-2K7IEVTA.js +43 -0
  40. package/dist/dist-3EIQTZHT.js +1380 -0
  41. package/dist/{dist-YA2BWZB2.js → dist-4U5L2X2C.js} +2 -2
  42. package/dist/{dist-UKMCJBB2.js → dist-54KAMNLO.js} +16 -15
  43. package/dist/dist-6M4MZWZW.js +58 -0
  44. package/dist/dist-6X576SU2.js +27 -0
  45. package/dist/dist-7QOEYLFX.js +103 -0
  46. package/dist/dist-AYBGHEDY.js +2541 -0
  47. package/dist/dist-EK45QNEM.js +45 -0
  48. package/dist/{dist-CS2VKNYS.js → dist-FKFEJRPX.js} +16 -15
  49. package/dist/dist-GTEJUBBT.js +66 -0
  50. package/dist/dist-HA74OKJZ.js +40 -0
  51. package/dist/dist-HU5RZAON.js +48 -0
  52. package/dist/dist-IYE3OBRB.js +374 -0
  53. package/dist/{dist-GJYT2OQV.js → dist-JLU26AB6.js} +12 -9
  54. package/dist/{dist-6G7JC2RA.js → dist-KUCI6JFE.js} +49 -9
  55. package/dist/dist-NUEMFZFL.js +33 -0
  56. package/dist/{dist-RKOGLK7R.js → dist-NUXMDXZ3.js} +31 -3
  57. package/dist/{dist-QAU3LGJN.js → dist-YCNWHSLN.js} +15 -5
  58. package/dist/{dist-CB5D5LMO.js → dist-YFFG2ZD6.js} +9 -16
  59. package/dist/dist-ZG4OKCSR.js +15 -0
  60. package/dist/doctor-SI4LLLDZ.js +345 -0
  61. package/dist/{export-import-4A5MWLIA.js → export-import-JFQH4KSJ.js} +1 -1
  62. package/dist/{history-3MOBX4MA.js → history-5NE46ZAH.js} +7 -7
  63. package/dist/hooks-installer-UN5JZLDQ.js +19 -0
  64. package/dist/index.js +395 -619
  65. package/dist/{init-6CH4HV5T.js → init-5FK3VKRT.js} +79 -13
  66. package/dist/job-HIDMAFW2.js +376 -0
  67. package/dist/jobs.memory-PLMMSFHB-VBECCTHN.js +33 -0
  68. package/dist/kiro-VMUHDFGK.js +153 -0
  69. package/dist/{launchd-LF2QMSKZ.js → launchd-6AWT54HR.js} +9 -17
  70. package/dist/mcp-PDUD7SGP.js +249 -0
  71. package/dist/mcp-installer-PQU3XOGO.js +259 -0
  72. package/dist/mcp-setup-OA7IB3H3.js +263 -0
  73. package/dist/{memory-Y6OZTXJ2.js → memory-ZNAEAK3B.js} +17 -17
  74. package/dist/{ollama-3XCUZMZT-FYKHW4TZ.js → ollama-3XCUZMZT-4JMH6B7P.js} +1 -1
  75. package/dist/{openai-E7G2YAHU-UYY4ZWON.js → openai-E7G2YAHU-T3HMBPH7.js} +2 -2
  76. package/dist/portal-JYWVHXDU.js +210 -0
  77. package/dist/prd-Q4J5NVAR.js +408 -0
  78. package/dist/repos-WWZXNN3P.js +271 -0
  79. package/dist/review-integration-5WHEJU2A.js +14 -0
  80. package/dist/{rules-E427DKYJ.js → rules-Y4VSOY5Y.js} +3 -3
  81. package/dist/run-VPNXEIBY.js +687 -0
  82. package/dist/server-COL4AXKU-P7S7NNF6.js +11 -0
  83. package/dist/server-KKSETHDV-XSSLEENT.js +20 -0
  84. package/dist/{skills-CX73O3IV.js → skills-QEYU2N27.js} +4 -2
  85. package/dist/start-JYOEL7AJ.js +303 -0
  86. package/dist/{status-4DFHDJMN.js → status-BHQYYGAL.js} +2 -2
  87. package/dist/{templates-U7T6MARD.js → templates-CBRUJ66V.js} +4 -3
  88. package/dist/tui-DP7736EX.js +61 -0
  89. package/dist/ulpi-5EN6JCAS-LFE3WSL4.js +10 -0
  90. package/dist/{uninstall-6SW35IK4.js → uninstall-ICUV6DDV.js} +3 -3
  91. package/dist/{update-M6IBJNYP.js → update-7ZMAYRBH.js} +3 -3
  92. package/dist/{version-checker-Q6YTYAGP.js → version-checker-4ZFMZA7Y.js} +2 -2
  93. package/package.json +39 -31
  94. package/dist/chunk-2MZER6ND.js +0 -415
  95. package/dist/chunk-2VYFVYJL.js +0 -4273
  96. package/dist/chunk-6OCEY7JY.js +0 -422
  97. package/dist/chunk-7LXY5UVC.js +0 -330
  98. package/dist/chunk-B55DDP24.js +0 -136
  99. package/dist/chunk-JWUUVXIV.js +0 -13694
  100. package/dist/chunk-MIAQVCFW.js +0 -39
  101. package/dist/chunk-YM2HV4IA.js +0 -505
  102. package/dist/ci-STSL2LSP.js +0 -370
  103. package/dist/mcp-installer-NQCGKQ23.js +0 -124
  104. package/dist/projects-ATHDD3D6.js +0 -271
  105. package/dist/review-ADUPV3PN.js +0 -152
  106. package/dist/server-USLHY6GH-AEOJC5ST.js +0 -18
  107. package/dist/server-X5P6WH2M-7K2RY34N.js +0 -11
  108. package/dist/skills/ulpi-generate-guardian/SKILL.md +0 -750
  109. package/dist/skills/ulpi-generate-guardian/references/framework-rules.md +0 -849
  110. package/dist/skills/ulpi-generate-guardian/references/language-rules.md +0 -591
  111. package/dist/ui-OWXZ3YSR.js +0 -167
  112. package/dist/ui.html +0 -698
@@ -1,750 +0,0 @@
1
- ---
2
- name: ulpi-generate-guards
3
- description: Use when the user asks to generate ULPI configuration for a project. Detects language, framework, package manager, and tooling to create optimized guards.yml with preconditions, permissions, postconditions, and pipelines. Invoke via /ulpi-generate-guards or when user says "generate guards", "create guards.yml", "setup ulpi", "configure guardian".
4
- ---
5
-
6
- <EXTREMELY-IMPORTANT>
7
- Before generating ANY guards.yml configuration, you **ABSOLUTELY MUST**:
8
-
9
- 1. Verify the target directory exists
10
- 2. Check for existing `.ulpi/guards.yml` (ask before overwriting)
11
- 3. Detect at least one technology signal (language, framework, or package manager)
12
-
13
- **Generating without verification = wrong rules, overwritten configs, broken guards**
14
-
15
- This is not optional. Every generation requires disciplined verification.
16
- </EXTREMELY-IMPORTANT>
17
-
18
- # Generate ULPI Configuration
19
-
20
- ## MANDATORY FIRST RESPONSE PROTOCOL
21
-
22
- Before generating ANY configuration, you **MUST** complete this checklist:
23
-
24
- 1. ☐ Verify target directory exists
25
- 2. ☐ Check for existing guards.yml
26
- 3. ☐ Detect language (tsconfig.json, pyproject.toml, go.mod, etc.)
27
- 4. ☐ Detect framework (next.config.*, artisan, manage.py, etc.)
28
- 5. ☐ Detect package manager (pnpm-lock.yaml, yarn.lock, etc.)
29
- 6. ☐ Announce: "Generating ULPI configuration for [language]/[framework]/[package_manager]"
30
-
31
- Do NOT ask "Proceed?" — the user invoked this skill explicitly. Show the detected stack as an informational summary, then generate immediately.
32
-
33
- **Generating WITHOUT completing this checklist = wrong or harmful rules.**
34
-
35
- ## Purpose
36
-
37
- This skill generates configuration for **ULPI**, a tool that:
38
- - Auto-approves safe operations (reads, package manager commands)
39
- - Blocks dangerous commands (force push, database wipes, env file edits)
40
- - Enforces best practices (read-before-write)
41
- - Runs postconditions (lint, test, generate) after file changes
42
-
43
- **Output:** `.ulpi/guards.yml` configuration file
44
-
45
- **Does NOT:** Install ULPI, run the generated rules, or modify existing configurations without confirmation.
46
-
47
- ## Overview
48
-
49
- Analyze a project directory, detect the technology stack, and generate a complete `guards.yml` configuration for ULPI. Creates rules that auto-approve safe operations, block dangerous commands, and enforce best practices.
50
-
51
- ## When to Use
52
-
53
- - User says "generate guards", "create guards.yml", "/ulpi-generate-guards"
54
- - User says "setup ulpi", "configure guardian for this project"
55
- - $ARGUMENTS contains a path (e.g., `/ulpi-generate-guards /path/to/project`)
56
-
57
- **Never generate unprompted.** Only when explicitly requested.
58
-
59
- ## Step 1: Determine Target Directory
60
-
61
- **Gate: Valid directory confirmed before proceeding to Step 2.**
62
-
63
- If $ARGUMENTS has a path, use it. Otherwise use current working directory.
64
-
65
- Verify the directory exists before proceeding. If not found, stop and inform the user.
66
-
67
- Check for existing `.ulpi/guards.yml`:
68
- - If found, ask user: merge, overwrite, or abort?
69
- - Never overwrite without explicit confirmation
70
-
71
- ## Step 2: Detect Technology Stack
72
-
73
- **Gate: Stack detected before proceeding to Step 3.**
74
-
75
- Scan for indicator files in priority order:
76
-
77
- ### Language Detection
78
-
79
- | Signal | Language |
80
- |--------|----------|
81
- | `tsconfig.json` | TypeScript |
82
- | `package.json` (no tsconfig) | JavaScript |
83
- | `pyproject.toml`, `requirements.txt` | Python |
84
- | `go.mod` | Go |
85
- | `Cargo.toml` | Rust |
86
- | `composer.json` | PHP |
87
- | `Gemfile` | Ruby |
88
- | `pom.xml`, `build.gradle` | Java |
89
- | `*.csproj`, `*.sln` | C# |
90
- | `mix.exs` | Elixir |
91
-
92
- ### Framework Detection
93
-
94
- | Signal | Framework |
95
- |--------|-----------|
96
- | `next.config.*` | Next.js |
97
- | `nuxt.config.*` | Nuxt |
98
- | `angular.json` | Angular |
99
- | `svelte.config.*` | SvelteKit |
100
- | `nest-cli.json` | NestJS |
101
- | `artisan` | Laravel |
102
- | `manage.py` + django | Django |
103
- | `fastapi` in deps | FastAPI |
104
- | `actix-web` in Cargo.toml | Actix |
105
- | `gin` in go.mod | Gin |
106
-
107
- ### Package Manager Detection
108
-
109
- | Signal | Package Manager |
110
- |--------|-----------------|
111
- | `pnpm-lock.yaml` | pnpm |
112
- | `yarn.lock` | yarn |
113
- | `package-lock.json` | npm |
114
- | `bun.lockb` | bun |
115
- | `poetry.lock` | poetry |
116
- | `uv.lock` | uv |
117
- | `Cargo.lock` | cargo |
118
- | `composer.lock` | composer |
119
- | `Gemfile.lock` | bundler |
120
-
121
- ### Tooling Detection
122
-
123
- | Signal | Tool | Type |
124
- |--------|------|------|
125
- | `vitest.config.*` | Vitest | test |
126
- | `jest.config.*` | Jest | test |
127
- | `pytest.ini` | pytest | test |
128
- | `.eslintrc*` | ESLint | lint |
129
- | `.prettierrc*` | Prettier | format |
130
- | `biome.json` | Biome | lint+format |
131
- | `prisma/schema.prisma` | Prisma | ORM |
132
- | `drizzle.config.*` | Drizzle | ORM |
133
-
134
- ### Monorepo Detection
135
-
136
- | Signal | Structure |
137
- |--------|-----------|
138
- | `turbo.json` | Turborepo |
139
- | `lerna.json` | Lerna |
140
- | `pnpm-workspace.yaml` | pnpm workspaces |
141
- | `"workspaces"` in package.json | Yarn/npm workspaces |
142
-
143
- **If a monorepo is detected, you MUST proceed to Step 2b (Map Monorepo Topology) before continuing.**
144
-
145
- ## Step 2b: Map Monorepo Topology (Monorepos Only)
146
-
147
- **Gate: Full workspace topology mapped before proceeding to Step 3.**
148
-
149
- When a monorepo is detected, do NOT treat it as a flat project. You must:
150
-
151
- 1. **Read the workspace config** — `pnpm-workspace.yaml`, `lerna.json`, or `package.json` workspaces field to find all workspace globs
152
- 2. **List all packages** — Resolve workspace globs to actual directories (e.g., `apps/*`, `packages/*`)
153
- 3. **Read each package's `package.json`** — Identify name, dependencies, devDependencies, scripts
154
- 4. **Map the dependency graph** — Which packages depend on which? Identify the direction of dependency flow
155
- 5. **Read the task runner config** — `turbo.json` task definitions, dependency chains (`^` prefix = depends on upstream)
156
- 6. **Identify build characteristics** — Does the package have a build step? Is it consumed as source? Does it have its own tsconfig?
157
-
158
- ### Topology Output Format
159
-
160
- Record the topology as a YAML comment in the header:
161
-
162
- ```yaml
163
- # Workspace Topology:
164
- # {package-a} → {package-b} (one-way dependency)
165
- # {package-c} (standalone)
166
- #
167
- # Task Graph (turbo.json):
168
- # build: depends on ^build
169
- # type-check: depends on ^type-check
170
- ```
171
-
172
- ### What Monorepo Topology Enables
173
-
174
- - **Package boundary enforcement** — Prevent imports in the wrong direction
175
- - **Per-package postconditions** — Type-check only the affected package using `turbo --filter=`
176
- - **Turbo-first commands** — Use `turbo run` instead of direct package manager for tasks defined in turbo.json
177
- - **Critical file cautions** — Barrel exports, shared configs, workspace manifests
178
-
179
- See `references/framework-rules.md` → Turborepo section for complete rule templates.
180
-
181
- ## Step 3: Extract Commands from Config
182
-
183
- **Gate: Commands extracted before proceeding to Step 4.**
184
-
185
- For Node.js projects, read package.json scripts to identify:
186
- - `test_command` (from "test" script)
187
- - `build_command` (from "build" script)
188
- - `lint_command` (from "lint" script)
189
- - `format_command` (from "format" script)
190
-
191
- **For monorepos:** Read BOTH the root `package.json` AND `turbo.json`:
192
- - If root scripts delegate to turbo (e.g., `"build": "turbo run build"`), the real commands are turbo tasks
193
- - Read each workspace's `package.json` scripts to understand what turbo invokes per-package
194
- - Postconditions and pipelines should use `turbo run <task> --filter=<package>`, NOT direct `pnpm <script>`
195
-
196
- For Python projects, check pyproject.toml for tool configurations.
197
-
198
- For Rust projects, use standard cargo commands.
199
-
200
- ## Step 4: Generate guards.yml
201
-
202
- **Gate: Complete rules generated before proceeding to Step 5.**
203
-
204
- Create `.ulpi/guards.yml` with these sections:
205
-
206
- ### Header
207
-
208
- ```yaml
209
- # ULPI — Generated Configuration
210
- # Stack: {language} / {framework} / {package_manager}
211
- # Generated: {timestamp}
212
-
213
- project:
214
- name: "{project_name}"
215
- runtime: "{runtime}"
216
- package_manager: "{package_manager}"
217
- ```
218
-
219
- ### Universal Preconditions (Always Include)
220
-
221
- ```yaml
222
- preconditions:
223
- read-before-write:
224
- enabled: true
225
- trigger: PreToolUse
226
- matcher: "Write|Edit|MultiEdit"
227
- requires_read: true
228
- message: "Read {file_path} before editing it."
229
- locked: true
230
- priority: 10
231
- ```
232
-
233
- ### Universal Permissions (Always Include)
234
-
235
- ```yaml
236
- permissions:
237
- # --- Auto-approvals ---
238
- auto-approve-reads:
239
- enabled: true
240
- trigger: PermissionRequest
241
- matcher: "Read|LS|Glob|Grep"
242
- decision: allow
243
- priority: 100
244
-
245
- auto-approve-git-readonly:
246
- enabled: true
247
- trigger: PermissionRequest
248
- matcher: Bash
249
- command_pattern: "git (status|log|diff|branch|show|stash list|remote -v|rev-parse)"
250
- decision: allow
251
- priority: 90
252
-
253
- auto-approve-gh-cli:
254
- enabled: true
255
- trigger: PermissionRequest
256
- matcher: Bash
257
- command_pattern: "gh"
258
- decision: allow
259
- priority: 80
260
-
261
- auto-approve-prettier:
262
- enabled: true
263
- trigger: PermissionRequest
264
- matcher: Bash
265
- command_pattern: "prettier"
266
- decision: allow
267
- priority: 80
268
-
269
- auto-approve-shell-inspection:
270
- enabled: true
271
- trigger: PermissionRequest
272
- matcher: Bash
273
- command_pattern: "(ls|cat|head|tail|wc|file|which|echo|pwd|whoami)"
274
- decision: allow
275
- priority: 80
276
-
277
- # --- Git destructive blocks (comprehensive) ---
278
- no-force-push:
279
- enabled: true
280
- trigger: PreToolUse
281
- matcher: Bash
282
- command_pattern: "git push.*(--force|-f)"
283
- decision: deny
284
- message: "Force push blocked. Use --force-with-lease."
285
- locked: true
286
- priority: 1
287
-
288
- no-git-checkout-dot:
289
- enabled: true
290
- trigger: PreToolUse
291
- matcher: Bash
292
- command_pattern: "git checkout \\."
293
- decision: deny
294
- message: "git checkout . discards all unstaged changes."
295
- locked: true
296
- priority: 1
297
-
298
- no-git-restore-dot:
299
- enabled: true
300
- trigger: PreToolUse
301
- matcher: Bash
302
- command_pattern: "git restore \\."
303
- decision: deny
304
- message: "git restore . discards all unstaged changes."
305
- locked: true
306
- priority: 1
307
-
308
- no-git-reset-hard:
309
- enabled: true
310
- trigger: PreToolUse
311
- matcher: Bash
312
- command_pattern: "git reset --hard"
313
- decision: deny
314
- message: "git reset --hard destroys uncommitted work."
315
- locked: true
316
- priority: 1
317
-
318
- no-git-clean-force:
319
- enabled: true
320
- trigger: PreToolUse
321
- matcher: Bash
322
- command_pattern: "git clean.* -f"
323
- decision: deny
324
- message: "git clean -f permanently deletes untracked files."
325
- locked: true
326
- priority: 1
327
-
328
- no-git-branch-delete-force:
329
- enabled: true
330
- trigger: PreToolUse
331
- matcher: Bash
332
- command_pattern: "git branch -D"
333
- decision: deny
334
- message: "git branch -D force-deletes branches. Use -d for safe delete."
335
- locked: true
336
- priority: 1
337
-
338
- no-skip-hooks:
339
- enabled: true
340
- trigger: PreToolUse
341
- matcher: Bash
342
- command_pattern: "--no-verify"
343
- decision: deny
344
- message: "Do not skip git hooks."
345
- locked: true
346
- priority: 1
347
-
348
- no-rm-rf:
349
- enabled: true
350
- trigger: PreToolUse
351
- matcher: Bash
352
- command_pattern: "rm -rf"
353
- decision: deny
354
- message: "rm -rf is destructive. Remove specific files instead."
355
- locked: true
356
- priority: 1
357
-
358
- # --- File protection ---
359
- block-env-files:
360
- enabled: true
361
- trigger: PreToolUse
362
- matcher: "Write|Edit"
363
- file_pattern: ".env*"
364
- decision: deny
365
- message: "Cannot edit .env files directly."
366
- priority: 50
367
-
368
- block-node-modules:
369
- enabled: true
370
- trigger: PreToolUse
371
- matcher: "Write|Edit"
372
- file_pattern: "node_modules/**"
373
- decision: deny
374
- locked: true
375
- priority: 1
376
-
377
- block-dist:
378
- enabled: true
379
- trigger: PreToolUse
380
- matcher: "Write|Edit"
381
- file_pattern: "**/dist/**"
382
- decision: deny
383
- locked: true
384
- priority: 1
385
- ```
386
-
387
- **Important:** `git push` is intentionally NOT auto-approved. Pushes affect shared state and should always require confirmation.
388
-
389
- ### Language-Specific Rules
390
-
391
- Add based on detected language. See `references/language-rules.md`.
392
-
393
- ### Framework-Specific Rules
394
-
395
- Add based on detected framework. See `references/framework-rules.md`.
396
-
397
- ### Pipelines (Required Fields)
398
-
399
- Every pipeline MUST include `on_failure`. It is a **required field** — omitting it causes a validation error.
400
-
401
- ```yaml
402
- pipelines:
403
- pre-commit-checks:
404
- enabled: true
405
- trigger: "PreToolUse"
406
- matcher: "Bash"
407
- command_pattern: "git commit"
408
- steps:
409
- - name: "type-check"
410
- run: "{type_check_command}"
411
- timeout: 60000
412
- - name: "lint"
413
- run: "{lint_command}"
414
- timeout: 60000
415
- on_failure: "block" # REQUIRED — "block" or "warn"
416
- message: "Pre-commit checks failed."
417
- locked: true
418
- priority: 5
419
- ```
420
-
421
- Valid `on_failure` values: `"block"` (prevent the action) or `"warn"` (show warning but allow).
422
-
423
- ## Step 5: Write Configuration
424
-
425
- **Gate: File written before proceeding to Step 6.**
426
-
427
- Create the `.ulpi/` directory if it doesn't exist.
428
-
429
- Write the generated YAML to `guards.yml`.
430
-
431
- Verify the file was written successfully.
432
-
433
- ## Step 6: Report Results
434
-
435
- **Gate: Results reported before marking complete.**
436
-
437
- Report to the user:
438
- - Stack detected
439
- - Rules created (counts)
440
- - File location
441
- - Suggested next steps
442
-
443
- ## Pre-Generation Checklist
444
-
445
- Before generating, verify:
446
- - [ ] Target directory exists and is accessible
447
- - [ ] No existing guards.yml OR user approved overwrite
448
- - [ ] At least one technology detected
449
-
450
- ## Error Handling
451
-
452
- | Situation | Action |
453
- |-----------|--------|
454
- | Directory not found | Stop and inform user |
455
- | No tech stack detected | Generate minimal universal rules only |
456
- | Multiple frameworks | Ask user which is primary |
457
- | Existing guards.yml | Ask: merge, overwrite, or abort |
458
- | Conflicting signals | Prefer more specific (framework > language) |
459
-
460
- ## About Postconditions
461
-
462
- Postconditions are **disabled by default** because they run automatically after file changes and may:
463
- - Slow down workflows
464
- - Produce unexpected side effects
465
- - Conflict with user's preferred workflow
466
-
467
- **To enable:** User should manually set `enabled: true` for desired postconditions after reviewing them.
468
-
469
- ## About Pipelines
470
-
471
- Pipelines define multi-step checks (e.g., pre-commit). Every pipeline **MUST** include the `on_failure` field — it is required. Valid values: `"block"` (stop the action) or `"warn"` (show warning but proceed).
472
-
473
- ```yaml
474
- pipelines:
475
- pre-commit-checks:
476
- enabled: true
477
- trigger: "PreToolUse"
478
- matcher: "Bash"
479
- command_pattern: "git commit"
480
- steps:
481
- - name: "type-check"
482
- run: "{type_check_command}"
483
- timeout: 60000
484
- - name: "lint"
485
- run: "{lint_command}"
486
- timeout: 60000
487
- on_failure: "block" # REQUIRED — omitting this causes validation error
488
- message: "Pre-commit checks."
489
- locked: true
490
- priority: 5
491
- ```
492
-
493
- ## Safety Rules
494
-
495
- | Rule | Reason |
496
- |------|--------|
497
- | Always include read-before-write | Prevents editing files without reading first |
498
- | Always block force push (--force AND -f) | Prevents history destruction |
499
- | Always block all git destructive ops | checkout ., restore ., reset --hard, clean -f, branch -D |
500
- | Always block --no-verify | Never skip git hooks |
501
- | Always block rm -rf | Prevents catastrophic deletions |
502
- | Always block .env edits | Protects secrets |
503
- | Always block node_modules/dist | Build artifacts should not be edited |
504
- | Auto-approve reads | Safe operations should not prompt |
505
- | Auto-approve ONLY the detected package manager | Do not auto-approve all package managers |
506
- | Never auto-approve git push | Pushes affect shared state, always confirm |
507
- | Never generate state-tracking rules | ULPI has no state; rules like "track last N" are non-functional |
508
- | Never generate redundant rules | If a rule duplicates another, remove the weaker one |
509
- | Always include `on_failure` in pipelines | Required field — omitting causes validation error |
510
- | Always map monorepo topology when detected | Flat treatment of monorepos produces wrong rules |
511
- | Never overwrite without asking | Preserves existing configuration |
512
- | Always verify directory exists | Prevents errors |
513
-
514
- ## Quick Reference: Command Detection
515
-
516
- ```
517
- package.json scripts:
518
- "test" → test_command
519
- "build" → build_command
520
- "lint" → lint_command
521
- "format" → format_command
522
- "dev" → auto-approve permission
523
-
524
- pyproject.toml:
525
- [tool.pytest] → pytest
526
- [tool.ruff] → ruff
527
- [tool.black] → black
528
-
529
- Cargo.toml:
530
- cargo test → test_command
531
- cargo build → build_command
532
- cargo clippy → lint_command
533
- ```
534
-
535
- ---
536
-
537
- ## Quality Checklist (Must Score 8/10)
538
-
539
- Score yourself honestly before marking generation complete:
540
-
541
- ### Detection Accuracy (0-2 points)
542
- - **0 points:** Guessed technology without file verification
543
- - **1 point:** Detected some signals but missed others
544
- - **2 points:** Verified all signals, detection matches reality
545
-
546
- ### Stack Announcement (0-2 points)
547
- - **0 points:** Generated without showing detected stack
548
- - **1 point:** Showed partial detection
549
- - **2 points:** Full detection shown before generation
550
-
551
- ### Rule Coverage (0-2 points)
552
- - **0 points:** Missing universal rules (read-before-write, block-env)
553
- - **1 point:** Universal rules present but missing language/framework rules
554
- - **2 points:** Complete coverage: universal + language + framework + tooling
555
-
556
- ### Safety Rules (0-2 points)
557
- - **0 points:** Missing critical blocks (force-push, env files)
558
- - **1 point:** Some safety rules but incomplete
559
- - **2 points:** All dangerous operations blocked
560
-
561
- ### Output Quality (0-2 points)
562
- - **0 points:** Invalid YAML or missing required fields
563
- - **1 point:** Valid but poorly organized
564
- - **2 points:** Clean, well-commented, properly structured YAML
565
-
566
- **Minimum passing score: 8/10**
567
-
568
- ---
569
-
570
- ## Common Rationalizations (All Wrong)
571
-
572
- These are excuses. Don't fall for them:
573
-
574
- - **"The directory is obvious"** → STILL verify it exists
575
- - **"I know this is a Node.js project"** → STILL detect from config files
576
- - **"There's no existing guards.yml"** → STILL check before generating
577
- - **"The user wants it fast"** → STILL show detected stack first
578
- - **"These are standard rules"** → STILL customize for detected stack
579
- - **"Postconditions are disabled anyway"** → STILL generate them correctly
580
- - **"It's a monorepo but I'll just use global commands"** → Map the topology and use per-package `--filter`
581
- - **"git push is just like other git commands"** → Push affects shared state, NEVER auto-approve it
582
- - **"I'll add a rule to track recent actions"** → ULPI has no state between invocations, this won't work
583
- - **"All Node.js package managers should be auto-approved"** → Only approve the DETECTED one
584
-
585
- ---
586
-
587
- ## Failure Modes
588
-
589
- ### Failure Mode 1: Wrong Technology Detection
590
-
591
- **Symptom:** Generated Python rules for a TypeScript project
592
- **Fix:** Always verify with config files, not assumptions
593
-
594
- ### Failure Mode 2: Overwritten Existing Config
595
-
596
- **Symptom:** User's custom guards.yml was replaced without warning
597
- **Fix:** Always check for existing file, ask before overwriting
598
-
599
- ### Failure Mode 3: Missing Critical Safety Rules
600
-
601
- **Symptom:** Agent force-pushed after generation (rule wasn't blocked)
602
- **Fix:** Always include universal safety rules regardless of stack
603
-
604
- ### Failure Mode 4: Invalid YAML Generated
605
-
606
- **Symptom:** ULPI fails to parse guards.yml
607
- **Fix:** Validate YAML structure before writing
608
-
609
- ### Failure Mode 5: Flat Treatment of Monorepo
610
-
611
- **Symptom:** Postconditions run `tsc --noEmit` globally instead of `turbo --filter=<pkg>`, package boundaries not enforced, no topology in header
612
- **Fix:** Always run Step 2b when monorepo is detected. Map the full workspace dependency graph. Generate per-package postconditions with `--filter`.
613
-
614
- ### Failure Mode 6: Non-Functional State-Tracking Rules
615
-
616
- **Symptom:** Rules reference "last N actions" or "track recent commands" — ULPI has no state between invocations
617
- **Fix:** Only generate rules that use ULPI's actual capabilities: matchers, patterns, triggers. No stateful tracking.
618
-
619
- ### Failure Mode 7: Redundant Rules
620
-
621
- **Symptom:** Multiple rules block the same thing (e.g., separate `block-dist` and `block-build-output` when only one output dir exists)
622
- **Fix:** Audit generated rules for overlap. Each rule should block a distinct concern.
623
-
624
- ---
625
-
626
- ## Quick Workflow Summary
627
-
628
- ```
629
- STEP 1: DETERMINE TARGET
630
- ├── Parse $ARGUMENTS for path
631
- ├── Default to current directory
632
- ├── Verify directory exists
633
- ├── Check for existing guards.yml
634
- └── Gate: Valid directory confirmed
635
-
636
- STEP 2: DETECT TECHNOLOGY
637
- ├── Scan for language signals
638
- ├── Scan for framework signals
639
- ├── Scan for package manager signals
640
- ├── Scan for tooling (test, lint, ORM)
641
- ├── Check for monorepo structure
642
- ├── Announce detected stack (informational, no question)
643
- └── Gate: Stack detected
644
-
645
- STEP 2b: MAP MONOREPO TOPOLOGY (if monorepo detected)
646
- ├── Read workspace config (pnpm-workspace.yaml, etc.)
647
- ├── List all packages in workspace
648
- ├── Read each package's package.json
649
- ├── Map dependency graph (who depends on whom)
650
- ├── Read turbo.json / lerna.json task definitions
651
- ├── Identify build characteristics per package
652
- └── Gate: Full topology mapped
653
-
654
- STEP 3: EXTRACT COMMANDS
655
- ├── Read package.json scripts (root + per-package for monorepos)
656
- ├── Read turbo.json tasks (monorepos)
657
- ├── Read pyproject.toml tools
658
- ├── Identify test/build/lint commands
659
- ├── For monorepos: note turbo --filter commands per package
660
- └── Gate: Commands extracted
661
-
662
- STEP 4: GENERATE RULES
663
- ├── Start with universal rules (comprehensive git blocks, no push auto-approve)
664
- ├── Add language-specific rules (only detected pkg manager)
665
- ├── Add framework-specific rules
666
- ├── Add monorepo rules (boundaries, per-pkg postconditions, prefer-turbo)
667
- ├── Add project-specific critical file cautions
668
- ├── Add tooling rules
669
- ├── Audit for redundancy (no duplicate rules)
670
- └── Gate: Complete rules generated
671
-
672
- STEP 5: WRITE CONFIGURATION
673
- ├── Create .ulpi/ directory
674
- ├── Write guards.yml
675
- ├── Verify file written
676
- └── Gate: File written
677
-
678
- STEP 6: REPORT RESULTS
679
- ├── Show stack summary
680
- ├── Show rule counts
681
- ├── Show file location
682
- ├── Suggest next steps
683
- └── Gate: Complete
684
- ```
685
-
686
- ---
687
-
688
- ## Completion Announcement
689
-
690
- When generation is complete, announce:
691
-
692
- ```
693
- ULPI configuration generated.
694
-
695
- **Quality Score: X/10**
696
- - Detection Accuracy: X/2
697
- - Stack Announcement: X/2
698
- - Rule Coverage: X/2
699
- - Safety Rules: X/2
700
- - Output Quality: X/2
701
-
702
- **Stack Detected:**
703
- - Language: [language]
704
- - Framework: [framework]
705
- - Package Manager: [package_manager]
706
- - Test Runner: [test_runner]
707
- - Linter: [linter]
708
-
709
- **Rules Generated:**
710
- - Preconditions: [count]
711
- - Permissions: [count]
712
- - Postconditions: [count]
713
-
714
- **Output:** .ulpi/guards.yml
715
-
716
- **Next steps:**
717
- Run `ulpi rules validate` to verify configuration.
718
- ```
719
-
720
- ---
721
-
722
- ## Integration with Other Skills
723
-
724
- The `ulpi-generate-guards` skill integrates with:
725
-
726
- - **`start`** — Detects ULPI configuration needs during project setup
727
- - **`commit`** — Generated rules can auto-approve git operations
728
- - **`create-pr`** — Generated rules can auto-approve PR creation commands
729
-
730
- **Workflow Chain:**
731
-
732
- ```
733
- New project or directory
734
-
735
-
736
- ulpi-generate-guards skill (this skill)
737
-
738
-
739
- guards.yml created
740
-
741
-
742
- ULPI uses rules during development
743
- ```
744
-
745
- ---
746
-
747
- ## Resources
748
-
749
- See `references/language-rules.md` for language-specific rule templates.
750
- See `references/framework-rules.md` for framework-specific rule templates.