@vegastack/skills 0.9.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/dist/index.js +5 -5
- package/package.json +1 -1
- package/skill/dev-architect/SKILL.md +93 -0
- package/skill/dev-architect/agents/openai.yaml +4 -0
- package/skill/dev-architect/references/ai-agents.md +89 -0
- package/skill/{architect → dev-architect}/references/data.md +43 -44
- package/skill/dev-architect/references/infra.md +98 -0
- package/skill/dev-architect/references/mobile.md +75 -0
- package/skill/{architect → dev-architect}/references/pinned-facts.md +17 -16
- package/skill/dev-architect/references/principles.md +117 -0
- package/skill/{architect → dev-architect}/references/security.md +37 -44
- package/skill/dev-architect/references/stack.md +38 -0
- package/skill/dev-architect/references/web.md +102 -0
- package/skill/{architect → dev-architect}/refresh/REFRESH.md +8 -6
- package/skill/{architect → dev-architect}/refresh/sources.json +5 -10
- package/skill/dev-implement/SKILL.md +3 -3
- package/skill/dev-intake/SKILL.md +2 -2
- package/skill/dev-setup/SKILL.md +8 -5
- package/skill/dev-setup/assets/dev-profile.md.template +19 -2
- package/skill/dev-setup/references/stack-playbooks.md +2 -2
- package/skill/skill-maintainer/references/release-ops.md +3 -3
- package/skill-integrity.json +20 -24
- package/skill/architect/SKILL.md +0 -68
- package/skill/architect/agents/openai.yaml +0 -4
- package/skill/architect/assets/adr-template.md +0 -21
- package/skill/architect/assets/arch-template.md +0 -20
- package/skill/architect/references/advisory.md +0 -102
- package/skill/architect/references/ai-agents.md +0 -95
- package/skill/architect/references/infra.md +0 -128
- package/skill/architect/references/mobile.md +0 -78
- package/skill/architect/references/principles.md +0 -91
- package/skill/architect/references/project-profile.md +0 -37
- package/skill/architect/references/stack.md +0 -38
- package/skill/architect/references/web.md +0 -152
|
@@ -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 (
|
|
10
|
-
passkey/OAuth-only users). Follow Better Auth's documented APIs — never hand-roll
|
|
11
|
-
or cache invalidation beside them.
|
|
12
|
-
- The organizations plugin (
|
|
13
|
-
organization maps to workspace; "user groups" of any
|
|
14
|
-
|
|
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.
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
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:
|
|
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
|
|
35
|
-
|
|
36
|
-
|
|
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
|
-
|
|
40
|
-
|
|
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
|
|
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
|
-
|
|
47
|
+
"intentionally public". Guest/anonymous write paths get the same rigor as authenticated
|
|
48
|
+
ones — never 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
|
|
52
|
-
|
|
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
|
|
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),
|
|
74
|
-
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
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.
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
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
|
|
95
|
-
|
|
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.
|
|
5
|
-
|
|
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).**
|
|
15
|
-
a pinned fact older than 60 days
|
|
16
|
-
and says so
|
|
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
|
|
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",
|
|
@@ -7,7 +7,7 @@ description: Implement an approved GitHub issue end to end without further user
|
|
|
7
7
|
|
|
8
8
|
One issue, one session, end to end: preflight → claim → build dark → verify → review → evidence in the issue → stop. The user reads the result in the issue on their own time; nothing here creates a PR or merges — those are `dev-ship`, on the user's word.
|
|
9
9
|
|
|
10
|
-
Nearest neighbor: `dev-intake` writes the brief this skill executes; if the issue turns out to need decisions, that's intake work — hand it back via `needs-operator`, don't guess. `.vegastack/dev.md` missing → run `dev-setup` first. Read dev.md before anything; its knobs (review, ui-evidence, tests, branch, stop-list) govern this whole skill.
|
|
10
|
+
Nearest neighbor: `dev-intake` writes the brief this skill executes; if the issue turns out to need decisions, that's intake work — hand it back via `needs-operator`, don't guess. `.vegastack/dev.md` missing → run `dev-setup` first. Read dev.md before anything; its knobs (review, ui-evidence, tests, branch, stop-list) govern this whole skill, and when the issue touches stack surfaces (schema, auth, hosting, services, jobs) its `## Architecture` section governs those choices the way the knobs govern process.
|
|
11
11
|
|
|
12
12
|
## Direct requests
|
|
13
13
|
|
|
@@ -19,7 +19,7 @@ The gates exist to stop agent-invented authority, never to slow the user down. W
|
|
|
19
19
|
- The issue is open, labeled `ready`, and carries the recorded approval comment (`Approved by … : "…"`). A label without the comment is not approval.
|
|
20
20
|
- No open blockers (issue dependencies) and no other assignee — an assigned or `working` issue belongs to someone else. A claim from a dead session is released only by the user: take over a `working` issue only when they explicitly hand it to you.
|
|
21
21
|
- Read the complete brief, plus parent issue and milestone for context. If the brief leaves a material decision open — including an unresolved Assumptions entry — do not start: label `needs-operator`, comment the smallest question that unblocks it, stop.
|
|
22
|
-
- Re-verify the brief against reality before coding: its cited touch points against the current code (things drift between approval and execution), and volatile dependency claims when stale or version-sensitive. Reality contradicting the brief is a stop — label `needs-operator` with the discrepancy; an approved brief is never a license to improvise past what's actually there.
|
|
22
|
+
- Re-verify the brief against reality before coding: its cited touch points against the current code (things drift between approval and execution), and volatile dependency claims when stale or version-sensitive (per `dev-architect`'s verify protocol). Reality contradicting the brief is a stop — label `needs-operator` with the discrepancy; an approved brief is never a license to improvise past what's actually there.
|
|
23
23
|
|
|
24
24
|
## Claim and branch
|
|
25
25
|
|
|
@@ -27,7 +27,7 @@ Assign yourself, swap `ready` → `working`. Branch from the default branch per
|
|
|
27
27
|
|
|
28
28
|
## Build — dark
|
|
29
29
|
|
|
30
|
-
No progress updates, no questions. A spike the brief flagged runs first — its result opens the evidence comment and shapes the rest of the build. Decide routine things yourself: file layout, helpers, fixtures, and root-cause fixes inside the issue's change areas. The brief's out-of-scope section and the dev.md stop-list bound you; hitting a stop condition (scope change, new dependency, spending, destructive/production action, unresolvable blocker) ends dark mode — post one `needs-operator` comment stating the smallest decision needed with your recommendation, and stop.
|
|
30
|
+
No progress updates, no questions. A spike the brief flagged runs first — its result opens the evidence comment and shapes the rest of the build. Decide routine things yourself: file layout, helpers, fixtures, and root-cause fixes inside the issue's change areas. A structural choice mid-build — a new dependency, table, or service — checks `dev-architect`'s trigger discipline first; a moving part with no named trigger is a stop condition, not a judgment call. The brief's out-of-scope section and the dev.md stop-list bound you; hitting a stop condition (scope change, new dependency, spending, destructive/production action, unresolvable blocker) ends dark mode — post one `needs-operator` comment stating the smallest decision needed with your recommendation, and stop.
|
|
31
31
|
|
|
32
32
|
Honesty over green: a failing test gets fixed at the root or reported as failing. Weakening a test, an assertion, or acceptance to pass is a cover-up, and cover-ups surface at review with interest.
|
|
33
33
|
|
|
@@ -14,7 +14,7 @@ Nearest neighbor: `dev-implement` consumes what this produces — intake writes
|
|
|
14
14
|
Finding facts is your job, never the user's — and a brief built on unverified facts is a confident mistake waiting for dark mode. The source can be one sentence in chat; thinner material just means the grounding and interview carry more weight. Before the first question:
|
|
15
15
|
|
|
16
16
|
- **Read the touched code.** Open the actual paths the feature would change: current behavior, existing patterns to reuse, where the new work plugs in. The brief cites these real paths later — a brief naming no files is a sign this step was skipped.
|
|
17
|
-
- **Verify dependencies.** Any library, service, or API capability the approach leans on gets checked against current official docs (docs tools or web search), noted with the date.
|
|
17
|
+
- **Verify dependencies.** Any library, service, or API capability the approach leans on gets checked against current official docs (docs tools or web search), noted with the date. Stack, schema, auth, and infra approach choices route through `dev-architect` — its verify-before-you-recommend protocol governs the check (pinned facts first, live docs on a miss or a fact older than 60 days); skip lookups for long-stable basics — judgment, not ritual.
|
|
18
18
|
- **Cross-check the request** against product docs and current behavior. A contradiction is pushback, never a silent resolution: "you asked for X; the code/docs currently do Y — which wins?" Push back on cost the same way: when a simpler version covers most of the need, name it.
|
|
19
19
|
- **Triage every unknown** into exactly three bins: *findable* → find it now, yourself; *only-the-user-knows* → ask, with a recommendation; *only-running-code-can-tell* → flag it as a spike that becomes the issue's first step. Guessing is not a bin.
|
|
20
20
|
|
|
@@ -32,7 +32,7 @@ Work the design the way a joint product-and-tech review would; each round's answ
|
|
|
32
32
|
|
|
33
33
|
1. **Product** — who this is for, the observable outcome, what's in and out of scope now, how it splits into slices or phases, priority.
|
|
34
34
|
2. **Behavior** — primary and alternate flows, rules, permissions, validations, edge and failure cases; for UI, the states, components, and copy.
|
|
35
|
-
3. **Technical** — only the choices that are genuinely the user's: approach trade-offs, data and interface implications, integrations, migration; recommend one and say why. When the project versions releases (dev.md `changelog:` knob), settle the intended version impact (patch/minor/major) here — the brief records it and dev-implement's changelog entry starts from it. Routine implementation stays the implementer's.
|
|
35
|
+
3. **Technical** — only the choices that are genuinely the user's: approach trade-offs, data and interface implications, integrations, migration; recommend one and say why — checking `dev-architect` first so a brief never proposes a recorded rejection or a moving part without its trigger. When the project versions releases (dev.md `changelog:` knob), settle the intended version impact (patch/minor/major) here — the brief records it and dev-implement's changelog entry starts from it. Routine implementation stays the implementer's.
|
|
36
36
|
4. **Quality and risk** — what proves it works (test cases, acceptance), what earns the `risky` label, what should stop a dark run beyond the standing stop-list.
|
|
37
37
|
|
|
38
38
|
These are the brief template's sections in interview form — a question exists only where reading the material, the codebase, and sensible defaults cannot fill a section.
|
package/skill/dev-setup/SKILL.md
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: dev-setup
|
|
3
|
-
description: Bootstrap a project for issue-driven agent development — existing repo or brand-new empty directory. Use when asked to "set up the dev workflow", "bootstrap this project for agents", "install the dev workflow here", "set up this new project", or invoked as dev-setup; also run automatically when dev-intake, dev-implement, or dev-ship find no .vegastack/dev.md in the project. Detects the stack and drafts its native release, changelog, and guard conventions; creates the project profile, the AGENTS.md dev section plus CLAUDE.md import, the workflow labels, and the decision register; offers release-guard workflows and the decision-capture hook on the user's yes. Not for architecture
|
|
3
|
+
description: Bootstrap a project for issue-driven agent development — existing repo or brand-new empty directory. Use when asked to "set up the dev workflow", "bootstrap this project for agents", "install the dev workflow here", "set up this new project", or invoked as dev-setup; also run automatically when dev-intake, dev-implement, or dev-ship find no .vegastack/dev.md in the project. Detects the stack and drafts its native release, changelog, and guard conventions; creates the project profile, the AGENTS.md dev section plus CLAUDE.md import, the workflow labels, and the decision register; offers release-guard workflows and the decision-capture hook on the user's yes. Not for architecture advice (that is dev-architect reading the dev.md Architecture section this skill writes), not for authoring skills, not for general CI or app scaffolding.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# dev-setup
|
|
7
7
|
|
|
8
8
|
Re-runnable bootstrap that gives a project everything the dev workflow needs: a profile file holding the knobs and runbooks, a thin AGENTS.md section that both Claude Code and Codex read, the GitHub labels, and the decision register. The other dev skills call this automatically when `.vegastack/dev.md` is missing, then continue with their original request.
|
|
9
9
|
|
|
10
|
-
Nearest neighbor: `architect`
|
|
10
|
+
Nearest neighbor: `dev-architect` consumes dev.md's `## Architecture` section and gives architecture advice; dev-setup detects the facts and writes the section. There is no separate architecture profile — dev.md is the one file.
|
|
11
11
|
|
|
12
12
|
## Step 1 — Detect before asking
|
|
13
13
|
|
|
@@ -21,7 +21,8 @@ Facts are your job; decisions are the user's. Gather these silently and present
|
|
|
21
21
|
| web app (UI evidence relevant) | framework dependencies (next, react, vue, …) |
|
|
22
22
|
| release/changelog machinery | match signals against [stack-playbooks](references/stack-playbooks.md) — the matched playbook drafts the `## Ship` runbook, the `changelog:` knob, and the guards to offer |
|
|
23
23
|
| environments and run commands | CI/deploy configs, env examples (names only), dev/start scripts — these draft `## Environments` and `## Verify` |
|
|
24
|
-
|
|
|
24
|
+
| architecture (app repos) | wrangler files (a `d1_databases` binding with no Postgres driver = the D1-only class), drizzle config, better-auth usage, `@aws-sdk/client-s3`/R2 bindings, pg-boss dependency, `eve`/`ai` packages, Dockerfiles/compose, pubspec.yaml — these draft `## Architecture` |
|
|
25
|
+
| existing files | AGENTS.md, CLAUDE.md, `.vegastack/dev.md`, a legacy `.vegastack/arch.md`, the decision register |
|
|
25
26
|
| existing labels | `gh label list` |
|
|
26
27
|
|
|
27
28
|
Not a git repo, or no origin remote → this is a **greenfield run, not an error**: follow the greenfield playbook in [stack-playbooks](references/stack-playbooks.md) — interview for the intended stack, offer `git init` and `gh repo create` each on its own yes, and render dev.md from the chosen playbook's conventions with TODO lines where machinery doesn't exist yet. A declined remote skips labels and records the TODO plainly.
|
|
@@ -30,7 +31,7 @@ Not a git repo, or no origin remote → this is a **greenfield run, not an error
|
|
|
30
31
|
|
|
31
32
|
Ask with your harness's question tool — AskUserQuestion in Claude Code, `request_user_input` in Codex where the mode allows it (availability details: [harness-facts](references/harness-facts.md)). When no question tool is available (headless run, gated mode), write the defaults, mark every unconfirmed knob `# TODO confirm`, and say so in your reply — a wrong invented preference costs more than a TODO.
|
|
32
33
|
|
|
33
|
-
**Round A — confirm the detected facts** in one compact summary (repo, stack, commands, web app or not, matched playbook). Ask only about what detection could not fill.
|
|
34
|
+
**Round A — confirm the detected facts** in one compact summary (repo, stack, commands, web app or not, matched playbook, detected architecture facts). Ask only about what detection could not fill.
|
|
34
35
|
|
|
35
36
|
**Round B — the workflow knobs**, recommended default first:
|
|
36
37
|
|
|
@@ -45,6 +46,8 @@ Ask with your harness's question tool — AskUserQuestion in Claude Code, `reque
|
|
|
45
46
|
- Guards drafted → offer to write their CI backstop steps into the project's workflow files (the local `guard:` lines run without CI); each file on the user's yes — release guards only, never general CI
|
|
46
47
|
- Environments or run commands detected → confirm the drafted `## Environments` and `## Verify` bullets
|
|
47
48
|
- Evidence repo (`ui-evidence: playwright`) → default is the owner's **shared** `<owner>/dev-review-evidence`; if it doesn't exist, offer `gh repo create <owner>/dev-review-evidence --private --add-readme` + the layout/retention README — created once, every project points at it. An org naming policy that rejects the name → pick the closest compliant name with the user and record it in the knob (the name is a knob value, not a contract)
|
|
49
|
+
- App architecture detected → confirm the drafted `## Architecture` (hosting, stage, and kind are what detection usually can't fill — ask those); nothing detected → delete the section, the `stack:` line is enough
|
|
50
|
+
- A legacy `.vegastack/arch.md` exists → fold its knob lines into `## Architecture`, offer each dated `notes:` line to the decision register on the user's yes, then offer to delete arch.md
|
|
48
51
|
- Decision-capture hook → offer the Stop-hook from [harness-facts](references/harness-facts.md) for the harnesses in use; hook files and settings wiring are written only on the user's explicit yes, merging into existing hook config, never overwriting
|
|
49
52
|
- AGENTS.md already has content → append the marked section (default) or show a merge proposal first
|
|
50
53
|
- CLAUDE.md already has content → add the `@AGENTS.md` import as its first line (default) or move its content into AGENTS.md and leave only the import
|
|
@@ -56,7 +59,7 @@ Everything else — merge style, branch naming, the stop-and-ask list — takes
|
|
|
56
59
|
|
|
57
60
|
| Target | Action |
|
|
58
61
|
|---|---|
|
|
59
|
-
| `.vegastack/dev.md` | render [dev-profile template](assets/dev-profile.md.template) with the answers — the project's single canonical process doc (short directional bullets; Ship/Verify/Environments/Design drafted from the playbook, Decisions test included, placeholders deleted, TODO lines where machinery is absent) |
|
|
62
|
+
| `.vegastack/dev.md` | render [dev-profile template](assets/dev-profile.md.template) with the answers — the project's single canonical process doc (short directional bullets; Ship/Verify/Environments/Design drafted from the playbook, Architecture drafted from detection, Decisions test included, placeholders deleted, TODO lines where machinery is absent) |
|
|
60
63
|
| `AGENTS.md` | create it, or insert/replace only the block between `<!-- vsk-dev:start -->` and `<!-- vsk-dev:end -->` using the [agents-section template](assets/agents-section.md.template); content outside the markers is the user's and stays untouched |
|
|
61
64
|
| `CLAUDE.md` | ensure its first line is `@AGENTS.md` — Claude Code does not read AGENTS.md natively and needs this import ([harness-facts](references/harness-facts.md)); create the file when absent |
|
|
62
65
|
| labels | `gh label create <name> --color <hex> --description "<text>"` for the names the `labels:` knob records, skipping ones that exist; default names and creation colors: `needs-operator` FBCA04 (waiting on the user) · `ready` 0E8A16 (approved, agent may start) · `working` 1D76DB (claimed by an agent) · `for-operator` 5319E7 (result awaiting user review) · `risky` B60205 (security, money, data, or production) |
|