@pikku/skills 0.12.20 → 0.12.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pikku/skills",
3
- "version": "0.12.20",
3
+ "version": "0.12.21",
4
4
  "description": "The Pikku agent skills — the instruction set coding agents read to build, wire and deploy Pikku projects",
5
5
  "author": "yasser.fadl@gmail.com",
6
6
  "license": "MIT",
@@ -237,12 +237,12 @@ Banning is the one capability with a schema requirement, and it has its own
237
237
  small plugin:
238
238
 
239
239
  ```typescript
240
- import { ban } from '@pikku/better-auth'
240
+ import { pikkuBan } from '@pikku/better-auth'
241
241
 
242
- betterAuth({ plugins: [ban()] })
242
+ betterAuth({ plugins: [pikkuBan()] })
243
243
  ```
244
244
 
245
- `ban()` adds `banned`, `banReason` and `banExpires` to `user` and refuses to
245
+ `pikkuBan()` adds `banned`, `banReason` and `banExpires` to `user` and refuses to
246
246
  create a session for a banned user, lapsing an expired ban as it goes. It makes
247
247
  no authorization decision — who may ban is decided by `admin:users:ban` — so it
248
248
  never needs to know about scopes or roles.
@@ -252,22 +252,28 @@ never needs to know about scopes or roles.
252
252
  Five, all imported from the package root and passed to `betterAuth({ plugins })`
253
253
  like any other. None is automatic — an app wires the ones it needs.
254
254
 
255
- | Plugin | Plugin `id` | Adds | Use it when |
256
- | ------------------- | ------------------ | ----------------------------------------------------------------------- | ------------------------------------------------------------- |
257
- | `ban()` | `pikku-ban` | `user.banned/banReason/banExpires` | You ban users (the schema + enforcement half of the above) |
258
- | `actor()` | `actor` | `POST /sign-in/actor`, `user.actor` | Scenarios or a dev switcher sign in as a persona |
259
- | `credentialOAuth()` | `credential-oauth` | `POST /credential-oauth/link`, `/credential-oauth/callback/:providerId` | An app links OAuth2 **API credentials** for a user |
260
- | `delegatedAuth()` | `delegated-auth` | `POST /sign-in/delegated` | An imported upstream API is the system of record for identity |
261
- | `fabric()` | `fabric` | `POST /sign-in/fabric` | A Fabric-deployed app lets a control-plane operator in |
255
+ | Plugin | Plugin `id` | Adds | Use it when |
256
+ | ------------------------ | ------------------ | ----------------------------------------------------------------------- | ------------------------------------------------------------- |
257
+ | `pikkuBan()` | `pikku-ban` | `user.banned/banReason/banExpires` | You ban users (the schema + enforcement half of the above) |
258
+ | `pikkuActor()` | `actor` | `POST /sign-in/actor`, `user.actor` | Scenarios or a dev switcher sign in as a persona |
259
+ | `pikkuCredentialOAuth()` | `credential-oauth` | `POST /credential-oauth/link`, `/credential-oauth/callback/:providerId` | An app links OAuth2 **API credentials** for a user |
260
+ | `pikkuDelegatedAuth()` | `delegated-auth` | `POST /sign-in/delegated` | An imported upstream API is the system of record for identity |
261
+ | `pikkuFabric()` | `fabric` | `POST /sign-in/fabric` | A Fabric-deployed app lets a control-plane operator in |
262
+
263
+ Every one carries a `pikku` prefix, because a `plugins: [...]` array mixes these
264
+ with better-auth's own and a bare `actor()` next to `organization()` says
265
+ nothing about where it came from. The unprefixed names — `ban`, `actor`,
266
+ `credentialOAuth`, `delegatedAuth`, `fabric` — are still exported as deprecated
267
+ aliases, so existing apps keep working.
262
268
 
263
269
  The plugin's `id` is what better-auth stores; the **export name** is what the
264
270
  inspector reads off your `plugins` array and what generated metadata is keyed
265
- by, so the two differ for `ban` and `delegatedAuth`.
271
+ by, so the two differ for every one of them.
266
272
 
267
- #### `credentialOAuth()` — link API credentials, not identities
273
+ #### `pikkuCredentialOAuth()` — link API credentials, not identities
268
274
 
269
275
  ```typescript
270
- credentialOAuth({
276
+ pikkuCredentialOAuth({
271
277
  config: [
272
278
  {
273
279
  providerId: 'github',
@@ -308,10 +314,10 @@ by construction. Tokens land in better-auth's `account` table, so
308
314
  An undeclared `providerId` is a 404; an anonymous caller a 401; a refused
309
315
  singleton a 403 that leaves no platform user behind.
310
316
 
311
- #### `delegatedAuth()` — the upstream API is the identity provider
317
+ #### `pikkuDelegatedAuth()` — the upstream API is the identity provider
312
318
 
313
319
  ```typescript
314
- delegatedAuth({
320
+ pikkuDelegatedAuth({
315
321
  authenticate: async ({ email, password, apiKey }) => upstream.login(...),
316
322
  storeCredential: (userId, identity) =>
317
323
  credentialService.set('acme', identity.credential, userId),
@@ -338,10 +344,10 @@ a warning and the user still gets in.
338
344
  `storeCredential` failing, by contrast, **fails the sign-in**: every proxied
339
345
  call would be dead anyway.
340
346
 
341
- #### `fabric()` — control-plane operator sign-in
347
+ #### `pikkuFabric()` — control-plane operator sign-in
342
348
 
343
349
  ```typescript
344
- fabric({ publicKey: FABRIC_AUTH_PUBLIC_KEY, scopeService, logger })
350
+ pikkuFabric({ publicKey: FABRIC_AUTH_PUBLIC_KEY, scopeService, logger })
345
351
  ```
346
352
 
347
353
  `POST /sign-in/fabric` verifies a short-lived RS256 token that the Fabric
@@ -468,9 +474,9 @@ someone" means **a particular kind of user** rather than one fixed admin.
468
474
  Register it explicitly — it is not automatic:
469
475
 
470
476
  ```typescript
471
- import { actor } from '@pikku/better-auth'
477
+ import { pikkuActor } from '@pikku/better-auth'
472
478
 
473
- plugins: [actor({ secret: SCENARIO_ACTOR_SECRET })]
479
+ plugins: [pikkuActor({ secret: SCENARIO_ACTOR_SECRET })]
474
480
  ```
475
481
 
476
482
  `POST ${basePath}/sign-in/actor` `{ email, secret, name? }` → 200 + the normal
@@ -585,7 +591,7 @@ await provisionPersonas(singletonServices, {
585
591
  ```
586
592
 
587
593
  It writes the same `banned` column the console's ban RPC writes (so it needs the
588
- `ban()` plugin wired, and says so if it isn't), revokes the account's sessions,
594
+ `pikkuBan()` plugin wired, and says so if it isn't), revokes the account's sessions,
589
595
  and leaves the row, its grants and its history intact — provisioning lifts the
590
596
  ban again by itself if the persona comes back. Deleting is deliberately not
591
597
  offered: an actor row is referenced by whatever those scenarios did while it
@@ -129,8 +129,8 @@ a stage whose pages return 200 — the shell renders fine — while its first da
129
129
  read throws `no result` or a foreign-key violation on a row the seed was
130
130
  silently supplying.
131
131
 
132
- A Better Auth app has a second constraint: the plugins you enable (`ban()`,
133
- `actor()`, …) each declare columns, and `pikku db migrate` refuses to run while
132
+ A Better Auth app has a second constraint: the plugins you enable (`pikkuBan()`,
133
+ `pikkuActor()`, …) each declare columns, and `pikku db migrate` refuses to run while
134
134
  the applied schema is missing any of them. `pikku db generate` writes the
135
135
  migration that closes the gap.
136
136
 
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  name: pikku-feature
3
3
  description: 'Drive create-a-feature work inside a Pikku project that already exists: discover project context, work on a feature branch, implement + verify + commit, and ask the user to review via the diff. TRIGGER when: the user asks to "create a feature", "add X to my Pikku project", "wire up a new endpoint", or anything that implies turning a natural-language request into Pikku functions/wirings/migrations within a working app. DO NOT TRIGGER when: the user asks for a one-off code edit in an existing function, asks about Pikku concepts (use pikku-concepts), or is building a whole app from a fresh scaffold rather than extending one (use pikku-build-app, or pikku-build-quick / pikku-build-platform).'
4
- allowed-tools: Bash(yarn pikku meta *), Bash(yarn pikku all *), Bash(yarn tsc), Bash(git status *), Bash(git diff *), Bash(git switch *), Bash(git checkout *), Bash(git checkout -b *), Bash(git add *), Bash(git commit *), Bash(git log *), Bash(git branch *)
4
+ allowed-tools: Bash(yarn pikku meta *), Bash(yarn pikku all *), Bash(yarn tsc), Bash(git status *), Bash(git diff *), Bash(git switch *), Bash(git checkout *), Bash(git checkout -b *), Bash(git add *), Bash(git commit *), Bash(git log *), Bash(git branch *), Bash(yarn pikku fabric report *), Bash(npx --no pikku fabric report *)
5
5
  argument-hint: '<feature description>'
6
6
  ---
7
7
 
@@ -16,6 +16,7 @@ Use this skill as an execution checklist, not reference material.
16
16
  3. Make the smallest source change that satisfies the task. Keep generated files generated, and avoid hand-editing SDKs, schema output, or typegen.
17
17
  4. Validate with the narrowest relevant command first, then run `pikku-verify` or `pikku all` when functions, wirings, schemas, or generated clients may have changed.
18
18
  5. If validation fails, fix the source cause and rerun validation. Do not paper over generated errors by editing generated files.
19
+ 6. Report anything about pikku itself that cost you time, the moment it happens — see **Report what fought you**.
19
20
 
20
21
  End-to-end flow: **discover → state intent → branch → implement → verify → commit → hand to reviewer**.
21
22
 
@@ -246,6 +247,106 @@ feature/<slug>` and surface the PR-create URL.
246
247
 
247
248
  Do not push without explicit confirmation. Do not merge.
248
249
 
250
+ ## Report what fought you
251
+
252
+ When pikku itself is what cost you time, report it with `pikku fabric report`.
253
+ Nothing is written to the repo; the finding goes to the linked fabric project
254
+ and the terminal shows you exactly what was sent.
255
+
256
+ **Report at the moment it happens**, not at the end from memory — a run that
257
+ falls over never reaches its end. One finding per thing that fought you.
258
+
259
+ ### The ladder
260
+
261
+ 1. **Find the quicker workaround.** The user is paying for their feature, not
262
+ for pikku's health.
263
+ 2. **Investigate** only when there is no workaround, or when the user asks why
264
+ something is slow or wrong.
265
+ 3. **Report at the depth you already reached.** Never spend extra effort to
266
+ file; never throw away effort you already spent. If the investigation took
267
+ you to the mechanism, the finding says so — named file, named function, what
268
+ is actually happening, and what pikku should do instead.
269
+
270
+ **Never fix pikku itself.** Not a patch in `node_modules`, not a linked
271
+ checkout, not a branch in the framework repo. Many agents each patching pikku to
272
+ unblock themselves is many divergent copies and a merge problem nobody signed up
273
+ for. Work around it in the app, report it, and let the fix happen once.
274
+
275
+ ### What counts
276
+
277
+ Anything that cost you time and would cost the next person the same. Most of
278
+ these never produce an error: output that is quietly wrong, a generated type
279
+ that disagrees with the runtime, a check that passes when it should not, a
280
+ narrowing you had to write by hand because the framework should have written it.
281
+ **Having to write code the framework should have written for you is a finding.**
282
+
283
+ So is anything that only shows up in one place — invisible locally, fatal
284
+ deployed, or the reverse. Say which, with `--surface`.
285
+
286
+ Not a finding: a preference, a thing you would have designed differently, or
287
+ baseline noise that was already failing before you started.
288
+
289
+ ### Two kinds
290
+
291
+ - `--kind product` — pikku behaved wrongly. Fixing it is a change to the
292
+ framework.
293
+ - `--kind harness` — a skill misled you: it told you to run something that does
294
+ not exist, described a flag that is spelled differently, or contradicted what
295
+ the CLI actually did. Pass `--skill <name>` and `--passage "<the line or
296
+ section>"`. This is the most useful kind to file, because it is fixable
297
+ immediately — so file it even when the cost was small.
298
+
299
+ ### When there was no workaround
300
+
301
+ Report it anyway with `--unresolved`, and put what you tried and how each
302
+ attempt failed in `--tried`. That is what stops the next person walking the same
303
+ dead ends. Tell the user what you did instead — abandoned it, shipped something
304
+ degraded, or stopped.
305
+
306
+ `--unresolved` means **no workaround was found**. It does not mean the
307
+ workaround was unpleasant.
308
+
309
+ ### The command
310
+
311
+ Send it as JSON on stdin. Most of a finding is prose, and prose carries
312
+ apostrophes, quotes, backticks and newlines — each one a shell metacharacter
313
+ before it is a character in your sentence. A stack trace passed to `--error`
314
+ breaks the command at its first newline; a backtick in `--actual` runs whatever
315
+ follows it. Quote the heredoc delimiter (`<<'EOF'`, never `<<EOF`) so the shell
316
+ leaves the body alone.
317
+
318
+ ```bash
319
+ pikku fabric report --stdin <<'EOF'
320
+ {
321
+ "title": "<one-line title>",
322
+ "kind": "product",
323
+ "model": "<the model you are>",
324
+ "expected": "<what you expected pikku to do>",
325
+ "actual": "<what it did instead>",
326
+ "command": "<the command you ran>",
327
+ "workaround": "<what you did instead, inside the app>"
328
+ }
329
+ EOF
330
+ ```
331
+
332
+ Add whichever of these you actually have: `error` (the error's message line,
333
+ verbatim), `repro` (the shortest way to reach it again), `proposal` (what pikku
334
+ should do), `area`, `surface` (`local`, `deployed` or `both`), `cost` (measured
335
+ if you measured it — "98s vs 20s steady" ranks; "slow" does not), `run` (an id
336
+ shared by every finding from this build), `deployTarget`.
337
+
338
+ The same fields exist as flags — `--kind`, `--expected` and so on — for a
339
+ finding short enough to type. Anything with a newline or a quote in it goes
340
+ through `--stdin`.
341
+
342
+ Versions, platform and package manager are read off the installed tree for you.
343
+ Do not pass them and do not ask the user for them.
344
+
345
+ Reporting never fails a build. A finding that cannot be sent — logged out, or
346
+ fabric unreachable — is held on the machine and goes out with the next report
347
+ that succeeds, so nothing you file is lost. If it says the finding was queued,
348
+ carry on with the feature; do not try to fix it, and do not file it again.
349
+
249
350
  ## Hard constraints
250
351
 
251
352
  The skill's `allowed-tools` does **not** permit:
@@ -254,7 +355,8 @@ The skill's `allowed-tools` does **not** permit:
254
355
  - `yarn dbmigrate` (never run migrations against the real DB during planning)
255
356
  - `pikku deploy apply` (never deploy)
256
357
  - secret writes
257
- - network calls beyond what the implementation requires
358
+ - network calls beyond what the implementation requires, except
359
+ `pikku fabric report`, which is explicitly permitted
258
360
 
259
361
  If the feature genuinely needs any of these, **stop and ask** with a clear
260
362
  explanation of why and what would change.