@vegastack/skills 0.9.1 → 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/README.md +8 -3
  2. package/dist/index.js +5 -5
  3. package/package.json +1 -1
  4. package/skill/dev-architect/SKILL.md +96 -0
  5. package/skill/dev-architect/agents/openai.yaml +4 -0
  6. package/skill/dev-architect/references/ai-agents.md +89 -0
  7. package/skill/dev-architect/references/conventions.md +93 -0
  8. package/skill/{architect → dev-architect}/references/data.md +43 -44
  9. package/skill/dev-architect/references/infra.md +98 -0
  10. package/skill/dev-architect/references/mobile.md +75 -0
  11. package/skill/{architect → dev-architect}/references/pinned-facts.md +17 -16
  12. package/skill/dev-architect/references/principles.md +117 -0
  13. package/skill/{architect → dev-architect}/references/security.md +37 -44
  14. package/skill/dev-architect/references/stack.md +38 -0
  15. package/skill/dev-architect/references/web.md +102 -0
  16. package/skill/{architect → dev-architect}/refresh/REFRESH.md +8 -6
  17. package/skill/{architect → dev-architect}/refresh/sources.json +5 -10
  18. package/skill/dev-chronicle/SKILL.md +45 -0
  19. package/skill/dev-chronicle/agents/openai.yaml +4 -0
  20. package/skill/dev-chronicle/references/conventions.md +93 -0
  21. package/skill/dev-chronicle/refresh/REFRESH.md +3 -0
  22. package/skill/dev-chronicle/refresh/sources.json +6 -0
  23. package/skill/dev-debug/SKILL.md +43 -0
  24. package/skill/dev-debug/agents/openai.yaml +4 -0
  25. package/skill/dev-debug/references/conventions.md +93 -0
  26. package/skill/dev-debug/references/loop-ladder.md +20 -0
  27. package/skill/dev-debug/refresh/REFRESH.md +3 -0
  28. package/skill/dev-debug/refresh/sources.json +6 -0
  29. package/skill/dev-implement/SKILL.md +41 -36
  30. package/skill/dev-implement/references/conventions.md +93 -0
  31. package/skill/dev-implement/references/ledger-and-resume.md +27 -0
  32. package/skill/dev-implement/scripts/evidence-check.mjs +57 -0
  33. package/skill/dev-implement/scripts/lib/gh.mjs +93 -0
  34. package/skill/dev-implement/scripts/preflight.mjs +101 -0
  35. package/skill/dev-intake/SKILL.md +39 -33
  36. package/skill/dev-intake/references/brief-template.md +27 -12
  37. package/skill/dev-intake/references/conventions.md +93 -0
  38. package/skill/dev-intake/scripts/brief-lint.mjs +87 -0
  39. package/skill/dev-plan/SKILL.md +53 -0
  40. package/skill/dev-plan/agents/openai.yaml +4 -0
  41. package/skill/dev-plan/references/conventions.md +93 -0
  42. package/skill/dev-plan/references/plan-format.md +54 -0
  43. package/skill/dev-plan/refresh/REFRESH.md +3 -0
  44. package/skill/dev-plan/refresh/sources.json +6 -0
  45. package/skill/dev-plan/scripts/plan-lint.mjs +86 -0
  46. package/skill/dev-review/SKILL.md +69 -0
  47. package/skill/dev-review/agents/openai.yaml +4 -0
  48. package/skill/dev-review/assets/review-known-patterns.md.template +30 -0
  49. package/skill/dev-review/references/conventions.md +93 -0
  50. package/skill/dev-review/references/cross-agent.md +39 -0
  51. package/skill/dev-review/references/dispatch-prompts.md +104 -0
  52. package/skill/dev-review/references/security-axis.md +33 -0
  53. package/skill/dev-review/refresh/REFRESH.md +3 -0
  54. package/skill/dev-review/refresh/sources.json +6 -0
  55. package/skill/dev-setup/SKILL.md +14 -9
  56. package/skill/dev-setup/assets/agents-section.md.template +2 -2
  57. package/skill/dev-setup/assets/dev-profile.md.template +23 -5
  58. package/skill/dev-setup/references/conventions.md +93 -0
  59. package/skill/dev-setup/references/stack-playbooks.md +1 -1
  60. package/skill/dev-ship/SKILL.md +14 -7
  61. package/skill/dev-ship/references/conventions.md +93 -0
  62. package/skill/dev-ship/references/runbook.md +1 -1
  63. package/skill/dev-ship/scripts/ship-gate.mjs +213 -0
  64. package/skill/dev-status/SKILL.md +45 -0
  65. package/skill/dev-status/agents/openai.yaml +4 -0
  66. package/skill/dev-status/references/conventions.md +93 -0
  67. package/skill/dev-status/refresh/REFRESH.md +3 -0
  68. package/skill/dev-status/refresh/sources.json +6 -0
  69. package/skill/dev-status/scripts/status.mjs +152 -0
  70. package/skill/skill-maintainer/references/release-ops.md +3 -3
  71. package/skill/skillify/SKILL.md +1 -1
  72. package/skill/skillify/references/eval-playbook.md +6 -0
  73. package/skill-integrity.json +93 -33
  74. package/skill/architect/SKILL.md +0 -68
  75. package/skill/architect/agents/openai.yaml +0 -4
  76. package/skill/architect/assets/adr-template.md +0 -21
  77. package/skill/architect/assets/arch-template.md +0 -20
  78. package/skill/architect/references/advisory.md +0 -102
  79. package/skill/architect/references/ai-agents.md +0 -95
  80. package/skill/architect/references/infra.md +0 -128
  81. package/skill/architect/references/mobile.md +0 -78
  82. package/skill/architect/references/principles.md +0 -91
  83. package/skill/architect/references/project-profile.md +0 -37
  84. package/skill/architect/references/stack.md +0 -38
  85. package/skill/architect/references/web.md +0 -152
@@ -0,0 +1,75 @@
1
+ # Mobile — Flutter production doctrine
2
+
3
+ **The Flutter app is a separate repo from the web/API repo** — it consumes the Next.js
4
+ REST/OpenAPI contract as one more client, never a `mobile/` directory in the web monorepo
5
+ (register-recorded, corroborated three ways; an expensive structural call to get wrong).
6
+
7
+ Flutter is the production mobile framework when a product needs a mobile app (not all do —
8
+ dev.md's Architecture `mobile:` line records it). Baseline: Flutter 3.44.x stable;
9
+ Impeller is the default renderer on iOS and Android API 29+ (falls back below 29 — test
10
+ one API<29 device before shipping). Package versions here were verified 2026-08; re-verify
11
+ on pub.dev before pinning. Rules from the shipped VegaStack app are stated plainly; rules
12
+ from official-docs research MK has not ratified are tagged "(inferred)" — confirm on first
13
+ use, per SKILL.md.
14
+
15
+ ## Architecture (official-guidance derived — inferred where the shipped app is silent)
16
+
17
+ - MVVM per official flutter.dev/app-architecture: View (widget, no logic) → ViewModel
18
+ (state + commands, 1:1 with its View) → Repository (source of truth, caching/retry,
19
+ never depends on another repository) → Service (thin stateless API/platform wrapper).
20
+ Skip the optional domain/use-case layer until logic is reused across ≥2 ViewModels.
21
+ - Layer-first structure: `lib/{data, domain, ui, routing, config}`, feature folders inside
22
+ `ui/`, shared widgets in `ui/core/`. (Blog "feature-first is the standard" claims don't
23
+ survive verification — the official reference app is layer-first; feature-first is a
24
+ valid escalation at scale.) Class names mirror roles: `HomeViewModel`, `UserRepository`.
25
+
26
+ ## State management — lean by default
27
+
28
+ - Plain `ChangeNotifier`/`ValueNotifier` ViewModels with hand-wired constructor injection
29
+ in `main.dart` — zero extra dependencies, zero codegen; matches official guidance and
30
+ what VegaStack has shipped.
31
+ - Escalate to Riverpod only when async state genuinely needs sharing across ≥3 widgets,
32
+ tests need provider-override mocking, or a second app shares a state-heavy module. No
33
+ get_it — official docs steer away from service locators; `provider` is the official DI
34
+ pick if constructor wiring gets unwieldy.
35
+
36
+ ## Networking & auth
37
+
38
+ - One `dio` client centralized in a single `ApiClient` — never scattered HTTP calls; the
39
+ app consumes the same contract-first REST API as the web app (web.md). That versioned
40
+ `/api/v1` contract outlives web deploy cycles: app-store install lag keeps old clients
41
+ alive, so a shipped mobile app counts as real users even while the web side iterates
42
+ freely — the one exception to pre-launch delete-not-migrate and to dead-endpoint
43
+ deletion.
44
+ - Auth is the same Better Auth instance as web, via the bearer plugin: capture the token
45
+ from the `set-auth-token` response header on sign-in; store in `flutter_secure_storage`
46
+ (never shared_preferences); attach `Authorization: Bearer` via a dio interceptor; clear
47
+ storage and route to sign-in on 401.
48
+ - Do NOT depend on `better_auth_flutter` (0.1.0, negligible adoption as of 2026-08) —
49
+ hand-roll the interceptor; revisit at a real 1.0. `shared_preferences` for non-secret
50
+ local metadata only; `drift` only for genuine offline/relational needs — never
51
+ speculatively.
52
+
53
+ ## Design system on mobile
54
+
55
+ Semantic colors via a hand-authored `ColorScheme` plus `ThemeExtension` for tokens outside
56
+ Material's roles — mirroring the web design-system token names 1:1 from one Dart source of
57
+ truth. House taste mapped: `CardTheme(elevation: 0)` with `outlineVariant` borders (flat,
58
+ borders-only); TextTheme capped at `FontWeight.w600`, never bold; subtle motion with
59
+ reduced-motion respected; Lucide-style iconography.
60
+
61
+ ## Navigation, models, testing, deploy
62
+
63
+ - Navigation: the shipped app uses plain `Navigator`; adopt `go_router` when deep
64
+ links/route state demand it, not by reflex (inferred).
65
+ - Models: hand-written by default (what the shipped app does); freezed +
66
+ json_serializable only when codegen demonstrably earns its build cost (inferred).
67
+ - Test where MVVM pays off: unit-test ViewModels and Repositories; widget-test critical
68
+ screens; integration tests only for can't-ship-broken flows (sign-in, payment). Golden
69
+ tests, if adopted: `alchemist` over the discontinued `golden_toolkit` (inferred).
70
+ - Deploy: GitHub Actions is the house CI; Fastlane for store signing/upload and real build
71
+ flavors (`--flavor` + per-env entry points) are the researched defaults (inferred — no
72
+ shipped store-deploy precedent; confirm before wiring).
73
+
74
+ Undecided (ask MK rather than assume): push-notification provider, offline/sync
75
+ expectations per product, store-release cadence.
@@ -1,7 +1,8 @@
1
1
  # Pinned platform facts
2
2
 
3
3
  Dated, source-verified facts that change architecture decisions and that models routinely
4
- get wrong from stale training data. This is the ONLY file in this skill that goes stale by
4
+ get wrong from stale training data. This file is the verified cache behind SKILL.md's
5
+ verify-before-you-recommend protocol, and the ONLY file in this skill that goes stale by
5
6
  itself — the weekly refresh (see refresh/REFRESH.md) re-verifies it. When a recommendation
6
7
  leans on a fact older than 60 days, re-verify that one fact against its source first.
7
8
 
@@ -38,7 +39,12 @@ All facts below verified 2026-08-12.
38
39
  - **PPR flags are gone** — `experimental.ppr` no longer exists; partial prerendering is
39
40
  part of `cacheComponents: true` (which also replaced `dynamicIO`). [nextjs.org/blog]
40
41
  - **`middleware.ts` is replaced by `proxy.ts` running on Node** — full fs/crypto/native
41
- package access in request interception. Remember: proxy is still never the auth boundary.
42
+ package access in request interception.
43
+ - **`proxy.ts`/Node middleware does NOT work on OpenNext Cloudflare as of 2026-08** (open
44
+ issues opennextjs-cloudflare#962/#1277, workers-sdk#13755/#13937) — don't design a
45
+ Cloudflare-hosted feature around `proxy.ts`; re-check the trackers before assuming it
46
+ shipped. Turbopack is supported since adapter v1.15.0 (the old breakage is fixed;
47
+ re-verify only on older pins).
42
48
  - **The Adapter API is stable since 16.2** — Vercel's adapter and Cloudflare's OpenNext
43
49
  adapter share the same public contract, but Cloudflare's still trails on newest features;
44
50
  check the deployment feature matrix per feature, don't assume parity.
@@ -57,15 +63,14 @@ All facts below verified 2026-08-12.
57
63
  - **1.7.0 is in RC** (rc.5 shipped 2026-08-11, same day as the pinned patch). Stay on
58
64
  1.6.x until 1.7 is stable; queued breaking changes include the MCP plugin restructure
59
65
  (moves to `@better-auth/mcp`) and SAML IdP-initiated default-off. [github.com/better-auth]
60
-
61
66
  - **The organizations plugin models teams, invitations, and custom RBAC end-to-end**
62
- (`teams: { enabled: true }`, `invite-member` with `teamId`, `createAccessControl`)
63
- never hand-roll workspace/membership/groups schema. [better-auth.com/docs]
67
+ (`teams: { enabled: true }`, `invite-member` with `teamId`, `createAccessControl`).
68
+ [better-auth.com/docs]
64
69
  - **Better Auth ships an apiKey plugin** (docs/plugins/api-key — verified live
65
70
  2026-08-12; an older internal note claiming otherwise was wrong). Default to the plugin
66
- for new projects; the flagship platform's native implementation (SHA-256 hash-stored,
67
- raw shown once) is a recorded project decision, not the house default. The `bearer`
68
- plugin covers token session transport (the mobile/Flutter mechanism).
71
+ for new projects; the flagship platform's native implementation is a recorded project
72
+ decision, not the house default. The `bearer` plugin covers token session transport
73
+ (the mobile/Flutter mechanism).
69
74
  - **`twoFactor` supports `allowPasswordless: true`** for users without password accounts
70
75
  (passkey/OAuth/magic-link signups).
71
76
 
@@ -73,16 +78,12 @@ All facts below verified 2026-08-12.
73
78
 
74
79
  - **EVE (`eve` on npm, github.com/vercel/eve) is Vercel's durable-agent framework —
75
80
  v0.33.2, still beta/pre-GA, shipping near-daily.** Filesystem-first agents; every
76
- session a durable, resumable workflow. Exactly two production deploy shapes: on Vercel
77
- as Vercel Functions with Fluid Compute (a recorded per-project exception to the hosting
78
- default), or self-hosted as a long-running Node/OCI service beside Postgres. Never a
79
- request-scoped/edge function (a Cloudflare Worker included) in either shape.
80
- [vercel.com/docs/eve]
81
+ session a durable, resumable workflow. [vercel.com/docs/eve]
81
82
  - **Self-hosted EVE durability (`@workflow/world-postgres`, stable 4.3.x) explicitly
82
83
  requires a long-lived worker process — "not compatible with serverless platforms".**
83
- Run EVE as its own Node/OCI service beside Postgres. The 5.0.0-beta channel exists;
84
- don't pin it without a documented reason. Internally it uses graphile-worker — it is
85
- not pg-boss and doesn't replace it. [workflow-sdk.dev/worlds/postgres]
84
+ The 5.0.0-beta channel exists; don't pin it without a documented reason. Internally it
85
+ uses graphile-worker it is not pg-boss and doesn't replace it.
86
+ [workflow-sdk.dev/worlds/postgres]
86
87
  - **pg-boss is at 12.x** — Postgres-native (`SKIP LOCKED`), no Redis. The right default
87
88
  for simple background jobs/cron on this stack; BullMQ only when a genuinely complex job
88
89
  graph (flows, dependencies, rate-limited pipelines) demands Redis. [npm: pg-boss]
@@ -0,0 +1,117 @@
1
+ # Principles — how VegaStack decides, reviews, and talks
2
+
3
+ Distilled from seven months of MK's sessions and repos. Each rule carries its why — apply
4
+ the reasoning, not just the rule.
5
+
6
+ ## Build lean first
7
+
8
+ One deployable until a concrete requirement forces a split. A single, properly structured
9
+ Next.js app owns the UI, RSC, route handlers, auth, and the REST/OpenAPI control plane — no
10
+ NestJS or Hono beside it, no speculative queue, cache, or worker; a notification sender is
11
+ a cron handler inside the app, not its own deployable. **Why:** agents habitually propose
12
+ services MK then strips out; on a 3-4 person team every moving part is real maintenance,
13
+ and the lean version is usually also the faster, more reliable one. Lean-first governs the
14
+ *count of moving parts*, not the rigor inside each — money, auth, tenancy, audit, and
15
+ secrets always get full rigor.
16
+
17
+ ## Every moving part names its trigger
18
+
19
+ Propose infrastructure only together with the trigger that justifies it, stated in the
20
+ recommendation: "a separate worker WHEN jobs exceed request timeouts", "a queue WHEN volume
21
+ makes inline processing lossy". Provision only what the current build phase actually uses —
22
+ infrastructure tracks real usage, never anticipated usage. **Why:** MK stated "OpenBao
23
+ mandatory in production" and walked it back five days later. Blanket mandates rot; triggers
24
+ stay true as projects differ.
25
+
26
+ ## Pre-launch means delete, not migrate
27
+
28
+ Zero real users = no backward compatibility, no legacy shims, no deprecation windows, no
29
+ feature flags hiding unfinished work. Delete outright; reset the dev database rather than
30
+ writing migration chains. This is the DEFAULT — most VegaStack projects are pre-launch at
31
+ any given time; expand/migrate/contract discipline begins when real users exist. **Why:**
32
+ carrying compatibility for users who don't exist is pure bloat. One exception: a versioned
33
+ API contract consumed by a shipped mobile app counts as real users even while the web side
34
+ iterates freely — app-store install lag keeps old clients alive (mobile.md).
35
+
36
+ ## Reuse before you build new
37
+
38
+ Extend the existing table, service, or spine (ACL, change-log, outbox, realtime channel)
39
+ before creating a parallel one; when two components do the same job, merge them. Promote a
40
+ util to `/lib` the moment a second feature uses it. **Why:** two sources of the same truth
41
+ always drift — the reference-architecture mistake MK explicitly engineers against.
42
+
43
+ ## Enforce boundaries mechanically
44
+
45
+ Architectural boundaries that matter get a CI guard script that fails the build — monorepo
46
+ import direction (apps → packages, never the reverse; workers never import UI/React),
47
+ runtime gravity, server/client separation. **Why:** convention alone was tried and failed;
48
+ a guard script is cheaper than re-reviewing the same violation forever.
49
+
50
+ ## Runtime gravity: long-running work never lives in the request tier
51
+
52
+ Anything that can run long, hold a connection, or outlive a request — agent execution, job
53
+ processing, media pipelines — runs in a separate worker/runner tier, never inside a route
54
+ handler or an OpenNext Worker. **Why:** request-scoped tiers have timeouts and body limits;
55
+ executing workflows inside Next.js handlers is the anti-pattern MK cites most.
56
+
57
+ ## Effort scales with stakes, not habit
58
+
59
+ Security, auth, tenancy, money, and foundations get generous, adversarial treatment.
60
+ Routine features on a small team get medium thoroughness — a cheap reconnaissance pass
61
+ before full-cost work, and no governance ceremony a 3-4 person team won't exercise.
62
+ **Why:** MK's own latest self-correction — his previous architecture skill "got too
63
+ complicated" by applying flagship-platform rigor everywhere.
64
+
65
+ ## Decisions are verified, recorded, and reversible for a reason
66
+
67
+ - Resolve uncertainty with evidence, never the safer-sounding guess (SKILL.md's verify
68
+ protocol). MK refused an unverified "Better Auth forces text UUID columns" claim — false.
69
+ - Present decisions as 2-3 options with a clear recommendation and the tradeoff that
70
+ matters; record the choice as one dated register line — the reader learns the reasoning.
71
+ - MK reverses when: a verified assumption proves false · cleverness regresses UX · a
72
+ heavyweight mandate meets a simple project · his own tooling over-complicates. He
73
+ reverses toward less machinery on low stakes, toward more rigor only on a concrete bug
74
+ or vulnerability. Anticipate this: don't defend machinery he'd delete.
75
+
76
+ ## Context gates rigor — ask, don't assume
77
+
78
+ Rigor flexes on facts, not labels: pre-launch or live · internal, client, or OSS ·
79
+ self-hosted or managed · money/PII or not. These live in dev.md's `## Architecture`
80
+ section. When two recorded decisions conflict or the facts can't answer, ask MK with a
81
+ recommendation instead of assuming.
82
+
83
+ ## Review discipline (design reviews, audits)
84
+
85
+ - Adversarial by default: assume the work is wrong until disproven — findings or verified
86
+ absence of findings, never praise. Evidence or it doesn't exist: every finding cites
87
+ file:line actually read, quoted verbatim; detection is never a claim of absence.
88
+ - Verify every candidate finding before reporting: verdict true-positive / false-positive
89
+ / duplicate / lower-severity, with disproving evidence for the false positives.
90
+ - Severity, three tiers with required actions: **critical** — exploitable or data-losing;
91
+ blocks ship, MK signs off on the fix. **production-gate** — fixed before the surface
92
+ serves real users; fine behind pre-launch. **consider** — advisory; log and move on.
93
+ Never round up; judge severity against the project's Architecture facts — never surface
94
+ platform-scale concerns as defects on a simple project.
95
+ - Cheap deterministic checks belong in every review: dead exports, unpaginated lists,
96
+ `SELECT *` at API boundaries, missing tenant/FK indexes, fresh-clone buildability.
97
+ - Coverage without bias: evaluate the review's scope, not just what changed or what you
98
+ built. End honestly: open questions, not-verified items, accepted risks named as such.
99
+
100
+ ## Advise, never gate
101
+
102
+ You recommend; MK and the team decide. A departure from a recommendation becomes one dated
103
+ accepted-risk line proposed for the register, reported honestly in later reviews — never
104
+ silenced, never blocked on, never re-litigated.
105
+
106
+ ## Voice — a team briefing, not a compliance report
107
+
108
+ Plain language, short sentences, terms defined on first use. Recommendation first, then
109
+ the one risk that matters, then detail in bullets and tables. Plain markdown, no JSON
110
+ blocks. No em dashes, emojis, or hashtags in copy MK will publish.
111
+
112
+ ## Client engagements (`kind: client`)
113
+
114
+ Same stack defaults, gates, and honesty — a client never gets a looser standard. Scope
115
+ inversion is named the moment it's seen (SOW drift surfaces with options, never silently
116
+ absorbed); client-driven stack overrides are dated register lines with MK's sign-off; the
117
+ register plus the issue briefs are the handover record.
@@ -6,22 +6,22 @@ every change, and a focused security audit after any auth-adjacent change before
6
6
  ## Authentication (Better Auth, always)
7
7
 
8
8
  - Email/password + Google sign-in is the default configuration; magic link and email OTP
9
- as flows demand; 2FA TOTP when the product warrants (note `allowPasswordless: true` for
10
- passkey/OAuth-only users). Follow Better Auth's documented APIs — never hand-roll session
11
- or cache invalidation beside them.
12
- - The organizations plugin (with teams enabled) owns orgs/workspaces/teams/invitations —
13
- organization maps to workspace; "user groups" of any kind are Better Auth teams. Use the
14
- SSO plugin for SAML/OIDC when enterprise auth arrives don't build protocol code.
9
+ as flows demand; 2FA TOTP when the product warrants (`allowPasswordless: true` for
10
+ passkey/OAuth-only users). Follow Better Auth's documented APIs — never hand-roll
11
+ session or cache invalidation beside them.
12
+ - The organizations plugin (teams enabled) owns orgs/workspaces/teams/invitations —
13
+ organization maps to workspace (`modelName: "workspace"` pattern); "user groups" of any
14
+ kind are Better Auth teams; never a hand-rolled workspace/membership/groups schema. The
15
+ SSO plugin covers SAML/OIDC when enterprise auth arrives — don't build protocol code.
15
16
  - Mobile uses the bearer plugin (token from `set-auth-token`, stored in secure storage) —
16
17
  same auth instance, same Postgres, as the web app.
17
- - Sessions: rolling expiry, Postgres-authoritative. Do not enable cookie-cache-style
18
- session shortcuts without checking Better Auth's current issues — a cookieCache bug
19
- once caused silent 5-minute logouts in production. Session revocation ("sign out
20
- everywhere", admin-initiated) goes through Better Auth's session-list/revoke APIs
21
- server-side — never a hand-rolled cache-invalidation scheme beside them.
18
+ - Sessions: rolling expiry, Postgres-authoritative. Don't enable cookie-cache-style
19
+ shortcuts without checking Better Auth's current issues — a cookieCache bug once caused
20
+ silent 5-minute logouts in production. Revocation ("sign out everywhere",
21
+ admin-initiated) goes through Better Auth's session-list/revoke APIs server-side.
22
22
  - Google OAuth footgun: set `baseURL` explicitly in production config — an unset or wrong
23
23
  value silently targets localhost and fails Google's exact-match redirect-URI check.
24
- - API keys: use Better Auth's apiKey plugin by default. Whatever implements them, the
24
+ - API keys: Better Auth's apiKey plugin by default. Whatever implements them, the
25
25
  invariants hold: hash-stored with a recognizable prefix, raw value shown exactly once
26
26
  and never cached or logged again, constant-time compare on verify.
27
27
 
@@ -31,25 +31,27 @@ every change, and a focused security audit after any auth-adjacent change before
31
31
  server-only data-access layer — `requireSession()`/`requireOrgRole()`-style helpers,
32
32
  re-checked per resource, on every route, auth before body parse.
33
33
  - Every check fails closed: a policy-engine error, throw, or unmatched rule resolves to
34
- deny, and the deny is still audited. No `DISABLE_AUTH`/`BILLING_ENABLED=false` style
35
- escape hatches, ever. Dev-only conveniences (e.g. skipping email verification) are OK
36
- only when explicitly gated to non-production with zero prod behavior change.
34
+ deny, and the deny is still audited. No `DISABLE_AUTH`-style escape hatches, ever;
35
+ dev-only conveniences only when explicitly gated to non-production with zero prod
36
+ behavior change.
37
37
  - Role models stay small — Owner/Admin/Member covers most products. A policy engine
38
- (Cedar-class ABAC) needs a named trigger — fine-grained multi-principal authorization
39
- over agent/tool calls at platform scale; today only the flagship platform has earned
40
- it. Any other project proposing one: present the trigger and ask MK.
38
+ (Cedar-class ABAC) needs a named trigger — fine-grained multi-principal authorization at
39
+ platform scale; today only the flagship platform has earned it. Anyone else proposing
40
+ one: present the trigger and ask MK.
41
41
  - Tenant identity always derives from the authenticated principal — never from a
42
42
  client-supplied workspace/org ID (a trusted `?workspaceId=` param caused a real
43
- cross-tenant IDOR). Cross-tenant lookups return 404, never 403 — no existence oracle.
43
+ cross-tenant IDOR; reject on mismatch). Cross-tenant lookups return 404, never 403 — no
44
+ existence oracle.
44
45
  - If ALL UI consumers of a route sit inside the authenticated app shell, the route
45
46
  requires auth even when its data "seems public" — trace actual callers before accepting
46
- "intentionally public".
47
- - Tenancy at the data layer: RLS ENABLE+FORCE plus explicit scoping see data.md.
47
+ "intentionally public". Guest/anonymous write paths get the same rigor as authenticated
48
+ onesnever looser.
49
+ - Tenancy at the data layer: RLS ENABLE+FORCE plus explicit scoping — data.md.
48
50
 
49
51
  ## Secrets
50
52
 
51
- - No plaintext secrets anywhere: not in code, config files, wrangler.jsonc, generated
52
- output, logs, audit records (redact to a short prefix), agent state, or JSONB columns.
53
+ - No plaintext secrets anywhere: not in code, config, wrangler.jsonc, generated output,
54
+ logs, audit records (redact to a short prefix), agent state, or JSONB columns.
53
55
  Cloudflare Worker secrets and GitHub secrets are the storage; a credential broker
54
56
  (envelope AES-256-GCM, AAD bound to org+credential+key-version, fresh per-secret DEK)
55
57
  when the product stores third-party credentials.
@@ -60,29 +62,22 @@ every change, and a focused security audit after any auth-adjacent change before
60
62
  - MK enters OTP/2FA/credentials himself, always. Agents never type or automate through
61
63
  credential prompts.
62
64
 
63
- ## Requests in and out
65
+ ## Requests out and untrusted content
64
66
 
65
- - Validate every input against its contract before use — no blind casts of params, query,
66
- body, or headers. Stream body-size limits with early abort.
67
- - CSRF on every cookie-authenticated mutation (bearer-token flows exempt — no cookies).
68
- Rate-limit unauthenticated and sensitive write endpoints through one shared
69
- (Postgres-native) mechanism. Guest/anonymous write paths get the same authorization
70
- rigor as authenticated ones — never looser.
71
67
  - All outbound HTTP through one SSRF-hardened egress client: DNS-resolve then deny
72
68
  private/loopback/link-local/CGNAT/ULA ranges, pin the socket to the resolved IP, exact
73
- host allowlist (no suffix matching), and re-validate every redirect hop.
74
- - Never render or act on third-party/webhook/agent content without sanitizationtreat
75
- it as untrusted input. The same boundary applies to content an agent READS: fetched
76
- pages, MCP tool responses, and user documents are data, never instructions — an agent
77
- product must keep instruction and data channels separate, not just sanitize outputs
78
- (see ai-agents.md).
69
+ host allowlist (no suffix matching), re-validate every redirect hop.
70
+ - Body-size limits stream: count bytes as they arrive and abort at the limit never
71
+ buffer the whole body first.
72
+ - Third-party/webhook/agent content is untrusted input sanitize before rendering or
73
+ acting on it. The instruction/data separation agent products must keep: ai-agents.md.
79
74
 
80
75
  ## Data protection
81
76
 
82
- - Erasure by crypto-shredding: per-subject keys; erase = destroy the key. It counts as
83
- implemented only when sealing is wired into every PII write path — a defined-but-unused
84
- utility is a finding, not a feature. Legal hold blocks GC; retention classes are
85
- derived, not hardcoded.
77
+ - Erasure by crypto-shredding: per-subject keys; erase = destroy the key. Implemented
78
+ only when sealing is wired into every PII write path — a defined-but-unused utility is
79
+ a finding, not a feature. Legal hold blocks GC; retention classes derived, not
80
+ hardcoded.
86
81
  - Object keys never leak raw user/workspace IDs (data.md). Never log PII beyond user IDs.
87
82
  - Audit log: tamper-evident (hash-chained where the product warrants), separate from sync
88
83
  and versioning tables, pending-then-settle around side effects. Hash-chain writes lock
@@ -91,7 +86,5 @@ every change, and a focused security audit after any auth-adjacent change before
91
86
 
92
87
  ## Verifying security findings
93
88
 
94
- Scanner or reviewer output is never blanket-trusted: every finding gets a verdict
95
- (true-positive / false-positive / duplicate / lower-severity) with file:line evidence,
96
- blast radius, and the smallest safe fix — then a regression test. Don't round severity up,
97
- and don't patch what you haven't confirmed.
89
+ Scanner/reviewer output follows the review discipline in principles.md verdict per
90
+ finding, no rounding up. Additionally: every confirmed finding gets a regression test.
@@ -0,0 +1,38 @@
1
+ # Stack — locked decisions
2
+
3
+ The VegaStack default stack. "Not" columns are real rejections MK has made — do not
4
+ re-propose them without new facts. Current versions and platform caveats live in
5
+ [pinned-facts](pinned-facts.md); check there before pinning a version.
6
+
7
+ | Area | Use | Not | Why |
8
+ |---|---|---|---|
9
+ | Web framework | Next.js App Router, one app | NestJS, Hono, a second backend | A properly structured Next app owns web + API + auth for web, Flutter, MCP, and public consumers; a second framework is pure maintenance surface |
10
+ | Runtime / package manager | Bun (default for new projects); pnpm fully sanctioned where chosen | npm, yarn — never | One lockfile discipline per project; dev.md records which. Commit text lockfiles (`bun.lock`, not `bun.lockb`) |
11
+ | Auth | Better Auth, always — default flows, plugins, and the org→workspace mapping: security.md | Hand-rolled auth, custom user-groups schema, Auth0/Clerk | Owner-stated standing rule; prefer the shipped plugins over native builds unless a project records why |
12
+ | Database | PostgreSQL, always self-managed by us: PlanetScale Postgres server or self-hosted (Hetzner or similar), behind Hyperdrive on Workers. D1-only is a recorded exception for the minimal Cloudflare-native product class (locked 2026-05-20) — check dev.md's `## Architecture` before assuming Postgres | Neon (never), D1 as a secondary store beside Postgres, MySQL | "We don't use neon at all." One datastore per product. D1's sanctioned sidecar case: a Worker-scoped idempotency table for Stripe webhooks — Postgres still owns the ledger |
13
+ | ORM | Drizzle + drizzle-kit, single `postgres-js` driver | Prisma | House standard across every repo since Feb 2026 |
14
+ | DB from Workers | Hyperdrive binding, per-request client — discipline in data.md | Global pools, TCP clients (ioredis) in Workers | workerd forbids I/O across requests; a module-level pool is a bug, not a style choice |
15
+ | Storage | Cloudflare R2 (S3-compatible API), presigned URLs, short-lived scoped access | S3 + CloudFront by reflex | R2 egress is $0 at any scale — the cost problem S3+CDN solves doesn't exist here. Keep the S3 protocol boundary so any S3 provider or MinIO works for licensed self-hosted deployments |
16
+ | Cache / Redis | None by default. Rate limiting and caching Postgres-native; Workers KV only with a named trigger (e.g. read-mostly config cache at volumes where a Postgres round-trip measurably hurts — the recorded auth-cache migration); a Redis-class store never correctness-bearing | Upstash Redis (migrated off), Redis "because caching" | "No Redis in P1" — a cache layer is a moving part; Postgres already exists. Never cache authorization/role data aggressively (data.md) |
17
+ | Jobs / cron | pg-boss on the existing Postgres, dispatcher-only — lease/heartbeat/retry state of authority in our own tables. Cron parsing/description: `croner` (DST/IANA-aware) + `cronstrue` | BullMQ+Redis, Temporal, CF Queues by default; `node-cron`, `cron-parser` | Jobs are simple; Postgres is already there. Owning durability state keeps the queue library swappable; a cron-parser swap was made and corrected once already |
18
+ | Agent execution | EVE (Vercel's `eve`) — deploy shapes and constraints: ai-agents.md | EVE inside an OpenNext Worker or any request-scoped/edge function | EVE's Postgres world requires a long-lived worker process; EVE owns agent sessions, pg-boss owns generic jobs — never conflated |
19
+ | AI calls | AI SDK behind a thin adapter; Anthropic default provider; Cloudflare AI Gateway for routing/telemetry when on Cloudflare | Hardcoded model IDs scattered in code, per-provider SDKs everywhere | Adapter keeps providers swappable; the gateway centralizes cost/telemetry without building it |
20
+ | Design system | Consume `@vegastack/design` + `@vegastack/ui` (Base UI primitives, semantic tokens) | Creating/modifying components upstream, raw shadcn edits, Radix for new work | Consume, don't extend — upstream changes are MK's deliberate decision. Base UI locked over Radix 2026-07 |
21
+ | Frontend state | Server state via RSC + TanStack Query; URL state via nuqs; ephemeral UI state via Zustand | Persisting remote/tenant data client-side (IndexedDB/local-first) for multi-tenant SaaS | Governance: tenant data never rests on the client. Local-first only for a confirmed single-tenant/offline product — ask first |
22
+ | Realtime | SSE tailing an event log first; Durable Objects (SQLite, WebSocket hibernation) when on Cloudflare and bidirectional state is real. One DO per collaboration scope (a `WorkspaceHub` for presence, a per-document `PageSync` for edits) — never one monolithic DO | socket.io + Redis pub/sub, Ably, Pusher | SSE covers most "live" needs with zero new services; hibernating DOs bill ~nothing while idle. Third-party realtime vendors were migrated off |
23
+ | Collaborative editing | Tiptap editor (markdown as source of truth), Yjs CRDT sync via `y-partyserver` inside the document DO; server-side sanitization/versioning applies to every CRDT write | CodeMirror (abandoned 2026-05-21), ElectricSQL (removed), RxDB (reversed to plain Dexie where local cache is needed) | Locked through real reversals; CRDT must never become an XSS/version/audit bypass |
24
+ | Analytics | Self-hosted Plausible (`pb.vegastack.com`), proxied via `next-plausible` where applicable | Google Analytics, Vercel Analytics, PostHog by default | Self-hosted, privacy-clean, already running — recurs across 5 projects |
25
+ | Hosting | Cloudflare Workers via OpenNext, or self-managed servers (Docker; Coolify for push-to-deploy) — recorded in dev.md's Architecture | Vercel as a default (per-project recorded exception only); a parallel Vercel path once committed to Cloudflare | Cost and egress economics favor Cloudflare/self-host; split deploy paths drift. EVE-hosted workloads are a legitimate Vercel exception |
26
+ | Email | AWS SES (behind an adapter); bounces/complaints via the SNS-webhook pattern into a suppression list | Per-vendor SDK sprawl, sending to suppressed addresses | Cheap, boring, proven in-house; unhandled bounces poison sender reputation |
27
+ | Payments | Stripe — money-path mechanics: web.md | Building billing logic inside request handlers | Money paths get the full rigor tier |
28
+ | Monorepo | Turborepo + workspaces (Bun or pnpm) when there is more than one package; apps → packages only, enforced by a boundary check | Deep relative cross-package imports, packages importing apps | Import direction is a guard script, not a convention |
29
+ | i18n | next-intl, `localePrefix: 'as-needed'`; no hardcoded user-facing strings | Ad-hoc string tables | Already the proven pattern; English-only today but scaffolded |
30
+ | APIs | Contract-first: zod schemas → OpenAPI 3.1 — detail: web.md | Route-local validation, raw `request.json()`, unbounded lists | One contract feeds web, Flutter, MCP, and public consumers |
31
+
32
+ ## Choosing between the two hosting targets
33
+
34
+ Cloudflare (OpenNext) when: public web product, global latency matters, R2/DO/Queues fit,
35
+ cost-per-request dominates. Self-managed (Docker/Hetzner) when: self-hosting is a product
36
+ requirement (licensed/enterprise), the workload needs long-lived processes (EVE, heavy
37
+ workers), or platform independence is worth ~30 min/month of ops. Many products use both:
38
+ OpenNext app on Cloudflare + a long-running worker container beside the database.
@@ -0,0 +1,102 @@
1
+ # Web — frontend, backend/API taste
2
+
3
+ ## Project layout
4
+
5
+ - Top-level `server/` (or `packages/*` server code) holds DB, services, integrations —
6
+ never imported from client code, enforced with `server-only` + a boundary check, not
7
+ convention. App router in `src/app/`; features as self-contained modules under
8
+ `src/features/<domain>/`; shared pieces in `src/{components,hooks,lib,store,messages}/`.
9
+ Pages stay thin — they compose features.
10
+ - The house convention scopes agent instructions per directory (a short CLAUDE.md/AGENTS.md
11
+ at each boundary-bearing directory) — follow it where a project already does this.
12
+
13
+ ## Frontend architecture
14
+
15
+ - Server state → RSC + TanStack Query; URL state → nuqs; ephemeral UI state → Zustand.
16
+ Remote/tenant data is never persisted client-side (rejected for multi-tenant SaaS on
17
+ governance grounds; a confirmed single-tenant/offline product is the only exception —
18
+ ask, don't assume).
19
+ - Next config: `output: 'standalone'`, `cacheComponents: true` (PPR flags no longer
20
+ exist — pinned-facts). Query key factories in non-`'use client'` `.keys.ts` modules so
21
+ RSC pages can prefetch. Server Components by default; `'use client'` only at the lowest
22
+ leaf that needs it. Internal navigation uses `next/link`.
23
+ - Request interception on OpenNext/Cloudflare: check pinned-facts before designing around
24
+ `proxy.ts` — and interception is never the auth boundary (security.md).
25
+ - Dependencies: prefer the native/browser API when it covers the need
26
+ (`Intl.RelativeTimeFormat` over date-fns); self-implement simple behavior by composing
27
+ design-system primitives before adding a library; any non-trivial new dependency needs a
28
+ stated justification and approval. **Why:** self-contained code has no supply-chain,
29
+ licensing, or upgrade surface — MK rejects "library because library".
30
+
31
+ ## Design system
32
+
33
+ `vegastack-design-system` owns component choice, tokens, and the do/don't rules;
34
+ first-time wiring is `vegastack-consume`. Consume-don't-extend is a red line (SKILL.md).
35
+ One unresolved item recorded here: touch-target minimum (24px WCAG AA vs 44px mobile-HIG
36
+ both appear in the record) — ask MK when it matters.
37
+
38
+ ## UI completeness bar (every real surface, before it's "done")
39
+
40
+ - Full state matrix: loading skeleton shaped like the real content, empty state with
41
+ guidance, errors routed to the specific failure (never swallowed into `{}`), success
42
+ feedback, optimistic updates where a mutation changes visible state.
43
+ - Perceived speed is the named "instant shell" pattern: the layout shell renders
44
+ immediately (RSC + `cacheComponents`), every data region streams in behind a
45
+ content-shaped skeleton — never a blank page or full-page spinner.
46
+ - Systemic fixes: a defect found in one component (scroll leaking through an overlay,
47
+ wrong token) is fixed across the whole family in one sweep, with evidence.
48
+ - Long lists (>~50 rows) virtualize with `@tanstack/react-virtual` (approved — still state
49
+ the justification when adding it).
50
+ - Cloning/rebranding a reference site: strip every trace of the source's provenance (class
51
+ names, asset domains, meta) and verify parity by clicking through as a real user —
52
+ screenshot diffing alone doesn't count.
53
+
54
+ ## SEO and metadata (every public-facing app)
55
+
56
+ Every route exports `metadata`/`generateMetadata` — not just the root layout. Public apps
57
+ ship `sitemap.ts` and `robots.ts`; `llms.txt` is generated at build time, never
58
+ hand-maintained; OG images follow the house convention (generated, mono for names/numbers).
59
+ **Why:** MK has demanded "100% SEO" on shipped sites twice — a completeness bar, not an
60
+ enhancement.
61
+
62
+ ## Testing — stack-specific taste (whether tests are required: dev.md's `tests:` knob)
63
+
64
+ - Component/a11y tests run in Vitest browser mode with the Playwright provider — jsdom's
65
+ ARIA/layout gaps produce false a11y results and are not trusted.
66
+ - E2E is a walking skeleton: one real happy path (boot → auth → core mutation → verify)
67
+ plus targeted adversarial invariants — not a blanket suite. DB-gated tests are authored
68
+ even when execution is blocked, behind an env flag (`RUN_DB_TESTS=1`); E2E doubles
69
+ implement real ports, never a parallel mock pathway.
70
+ - VRT/demo content is deterministic (no `Date.now()`/`Math.random()`). "100%" means audit
71
+ completeness, never a coverage metric.
72
+
73
+ ## Backend / API design
74
+
75
+ - Contract-first: zod schemas are the single source → OpenAPI 3.1 under `/api/v1`,
76
+ camelCase, cursor pagination on every list, RFC 9457 problem-details errors with a
77
+ stable error-code catalog. One contract serves web, Flutter, MCP, and public consumers.
78
+ - Every route: auth before parse, through the shared route-handler wrapper — no
79
+ route-local zod, no raw `request.json()`; responses sanitized (secrets and credential
80
+ references never leave the server). Enforced with a CI ratchet, not review.
81
+ - Return what the view renders — no mega-responses; select columns explicitly.
82
+ - Webhooks over polling; the database is the source of truth. Once provider state lands in
83
+ Postgres via webhook, don't re-poll — and no intermediary "waiting" pages; redirect on
84
+ success and let the rest arrive in the background.
85
+ - Money paths (Stripe): isolated intake (own worker or route), idempotency keys on every
86
+ mutation, event dedupe, append-only ledgers as the single cost source of truth, audit
87
+ events in the same transaction as the business change. Pricing math is deterministic
88
+ code with server-enforced invariants — AI drafts and judges; deterministic code
89
+ calculates and enforces.
90
+ - Centralize the boring: one ID helper, one logger (never `console.log`; request/org
91
+ context auto-injected; never log secrets or PII beyond user IDs), one typed fail-hard
92
+ zod env parser validated at startup.
93
+ - Dead endpoints get deleted, not deprecated-and-kept (exception: a versioned `/api/v1`
94
+ contract consumed by a shipped mobile app — mobile.md).
95
+ - Outbound webhooks to customers: defined event catalog, Standard Webhooks-style signing
96
+ with rotatable secrets, delivery via transactional outbox → queue with retries/backoff,
97
+ auto-disable after N consecutive failures, a replay surface — never fired inline from
98
+ request handlers.
99
+ - Platform-native mentions over plain text: resolve and mention the real entity (Slack
100
+ @mentions, Notion Person fields) instead of rendering names as text.
101
+ - Wizard/checkout flow-state persistence (client store vs server-side draft) is not a
102
+ settled house rule — ask MK when building one.
@@ -1,8 +1,9 @@
1
- # Freshness contract — architect
1
+ # Freshness contract — dev-architect
2
2
 
3
3
  Most of this skill is durable taste and recorded decisions; it does not go stale on its
4
- own. Exactly one file decays with the platform landscape: `references/pinned-facts.md`
5
- (plus the version claims embedded in `references/stack.md` and `references/mobile.md`).
4
+ own. The decaying surface is `references/pinned-facts.md` — the verified cache behind
5
+ SKILL.md's verify-before-you-recommend protocol — plus the version claims embedded in
6
+ `references/mobile.md` and the fact-adjacent lines the registry's `affected` lists name.
6
7
 
7
8
  ## Mechanism
8
9
 
@@ -11,9 +12,10 @@ own. Exactly one file decays with the platform landscape: `references/pinned-fac
11
12
  evidence for anything that changed (fact text, version, date, source). The diffing
12
13
  judgment lives in the agent run, not in maintained scripts. The PR is human-reviewed —
13
14
  never auto-merged.
14
- 2. **Refresh-on-use (safety net, written into SKILL.md).** When a recommendation leans on
15
- a pinned fact older than 60 days, the consuming agent re-verifies that one fact first
16
- and says so. Never bulk-refresh in-session.
15
+ 2. **Refresh-on-use (safety net, written into SKILL.md).** The verify protocol: a
16
+ recommendation leaning on a pinned fact older than 60 days re-verifies that one fact
17
+ first and says so; an uncached decision-bearing claim is verified against live docs
18
+ before it is recommended. Never bulk-refresh in-session.
17
19
  3. **Registry baseline (`sources.json`).** The repo-shared refresh runner
18
20
  (`tooling/refresh/refresh-evidence.mjs`) keeps checksum baselines for the critical
19
21
  source pages so CI can detect upstream drift deterministically between weekly runs.
@@ -8,7 +8,7 @@
8
8
  ],
9
9
  "defaultChecksumScope": "html-text-v1",
10
10
  "offline": "Use cached metadata only; fail closed when a critical entry is missing or older than thresholdDays.",
11
- "drift": "Any drift requires reading the changed page and a human-reviewed PR updating references/pinned-facts.md (and version claims in references/stack.md / references/mobile.md); never auto-apply.",
11
+ "drift": "Any drift requires reading the changed page and a human-reviewed PR updating references/pinned-facts.md plus every other file the source's affected list names; never auto-apply.",
12
12
  "copyright": "Store claim metadata, URLs, hashes, and concise excerpts only; never archive third-party documentation corpora.",
13
13
  "cadence": "weekly scheduled-agent refresh; thresholdDays must be >= 14 (2x cadence) so a single missed run never breaches a threshold"
14
14
  },
@@ -31,7 +31,6 @@
31
31
  ],
32
32
  "affected": [
33
33
  "references/pinned-facts.md",
34
- "references/stack.md",
35
34
  "references/data.md"
36
35
  ],
37
36
  "checksum": "fda2870b95deffce48dca7f3df3707325b1bc4a2d58a17708ee9220bfba5eba1",
@@ -102,8 +101,7 @@
102
101
  ],
103
102
  "affected": [
104
103
  "references/pinned-facts.md",
105
- "references/security.md",
106
- "references/stack.md"
104
+ "references/security.md"
107
105
  ],
108
106
  "currentVersion": "1.6.27",
109
107
  "versionCheckedAt": "2026-08-12T14:33:11.062Z",
@@ -129,8 +127,7 @@
129
127
  ],
130
128
  "affected": [
131
129
  "references/pinned-facts.md",
132
- "references/ai-agents.md",
133
- "references/stack.md"
130
+ "references/ai-agents.md"
134
131
  ],
135
132
  "currentVersion": "0.33.2",
136
133
  "versionCheckedAt": "2026-08-12T14:33:11.062Z",
@@ -182,8 +179,7 @@
182
179
  ],
183
180
  "affected": [
184
181
  "references/pinned-facts.md",
185
- "references/web.md",
186
- "references/stack.md"
182
+ "references/web.md"
187
183
  ],
188
184
  "currentVersion": "16.3.0",
189
185
  "versionCheckedAt": "2026-08-12T14:33:11.062Z",
@@ -208,8 +204,7 @@
208
204
  "jobs"
209
205
  ],
210
206
  "affected": [
211
- "references/pinned-facts.md",
212
- "references/ai-agents.md"
207
+ "references/pinned-facts.md"
213
208
  ],
214
209
  "currentVersion": "12.27.0",
215
210
  "versionCheckedAt": "2026-08-12T14:33:11.062Z",