@event4u/agent-config 2.10.0 → 2.12.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/.agent-src/commands/agents.md +1 -0
- package/.agent-src/commands/challenge-me.md +1 -0
- package/.agent-src/commands/chat-history.md +1 -0
- package/.agent-src/commands/context.md +1 -0
- package/.agent-src/commands/council.md +1 -0
- package/.agent-src/commands/feature.md +1 -0
- package/.agent-src/commands/fix.md +1 -0
- package/.agent-src/commands/grill-me.md +1 -0
- package/.agent-src/commands/judge.md +1 -0
- package/.agent-src/commands/memory.md +1 -0
- package/.agent-src/commands/module.md +1 -0
- package/.agent-src/commands/onboard.md +32 -4
- package/.agent-src/commands/optimize.md +1 -0
- package/.agent-src/commands/override.md +1 -0
- package/.agent-src/commands/roadmap.md +1 -0
- package/.agent-src/commands/tests.md +1 -0
- package/.agent-src/skills/canvas-design/SKILL.md +132 -0
- package/.agent-src/skills/canvas-design/evals/triggers.json +16 -0
- package/.agent-src/skills/doc-coauthoring/SKILL.md +129 -0
- package/.agent-src/skills/doc-coauthoring/evals/triggers.json +16 -0
- package/.agent-src/skills/nextjs-patterns/SKILL.md +203 -0
- package/.agent-src/skills/skill-writing/SKILL.md +101 -16
- package/.agent-src/skills/sql-writing/SKILL.md +1 -1
- package/.agent-src/skills/symfony-workflow/SKILL.md +173 -0
- package/.agent-src/templates/scripts/work_engine/hook_bootstrap.py +4 -0
- package/.agent-src/templates/scripts/work_engine/hooks/builtin/__init__.py +3 -0
- package/.agent-src/templates/scripts/work_engine/hooks/builtin/decision_gate.py +162 -0
- package/.agent-src/templates/scripts/work_engine/hooks/settings.py +24 -6
- package/.agent-src/templates/scripts/work_engine/scoring/decision_engine.py +351 -0
- package/.claude-plugin/marketplace.json +5 -1
- package/CHANGELOG.md +68 -0
- package/README.md +37 -8
- package/config/agent-settings.template.yml +66 -0
- package/docs/architecture.md +1 -1
- package/docs/contracts/STABILITY.md +16 -0
- package/docs/contracts/adr-chat-history-split.md +1 -0
- package/docs/contracts/adr-forecast-construction-shape.md +1 -0
- package/docs/contracts/adr-gtm-context-spine.md +1 -0
- package/docs/contracts/adr-level-6-productization.md +147 -0
- package/docs/contracts/adr-settings-sync-engine.md +1 -0
- package/docs/contracts/adr-wing4-context-spine.md +1 -0
- package/docs/contracts/agent-memory-contract.md +1 -0
- package/docs/contracts/agents-md-tech-stack.md +1 -0
- package/docs/contracts/audit-log-v1.md +1 -0
- package/docs/contracts/command-clusters.md +1 -0
- package/docs/contracts/command-surface-tiers.md +1 -0
- package/docs/contracts/context-paths.md +1 -0
- package/docs/contracts/cost-profile-defaults.md +105 -0
- package/docs/contracts/cross-wing-handoff.md +1 -0
- package/docs/contracts/decision-engine-gates.md +115 -0
- package/docs/contracts/decision-trace-v1.md +1 -0
- package/docs/contracts/file-ownership-matrix.md +1 -0
- package/docs/contracts/hook-architecture-v1.md +1 -0
- package/docs/contracts/implement-ticket-flow.md +1 -0
- package/docs/contracts/installed-tools-lockfile.md +1 -0
- package/docs/contracts/kernel-membership.md +1 -0
- package/docs/contracts/linear-ai-rules-inclusion.md +1 -0
- package/docs/contracts/linear-ai-three-layers.md +1 -0
- package/docs/contracts/linter-structural-model.md +1 -0
- package/docs/contracts/load-context-budget-model.md +1 -0
- package/docs/contracts/load-context-schema.md +1 -0
- package/docs/contracts/memory-visibility-v1.md +1 -0
- package/docs/contracts/one-off-script-lifecycle.md +1 -0
- package/docs/contracts/orchestration-dsl-v1.md +1 -0
- package/docs/contracts/package-self-orientation.md +1 -0
- package/docs/contracts/persona-schema.md +1 -0
- package/docs/contracts/release-trunk-sync.md +104 -0
- package/docs/contracts/roadmap-complexity-standard.md +1 -0
- package/docs/contracts/rule-classification.md +1 -0
- package/docs/contracts/rule-interactions.md +26 -0
- package/docs/contracts/rule-priority-hierarchy.md +1 -0
- package/docs/contracts/rule-router.md +1 -0
- package/docs/contracts/settings-sync-yaml-subset.md +1 -0
- package/docs/contracts/skill-domains.md +1 -0
- package/docs/contracts/tier-3-contrib-plugin.md +1 -0
- package/docs/contracts/ui-stack-extension.md +1 -0
- package/docs/contracts/ui-track-flow.md +1 -0
- package/docs/customization.md +1 -1
- package/docs/getting-started.md +3 -1
- package/docs/installation.md +8 -6
- package/package.json +1 -1
- package/scripts/ai_council/clients.py +17 -4
- package/scripts/ai_council/orchestrator.py +6 -2
- package/scripts/check_beta_review_markers.py +127 -0
- package/scripts/check_references.py +25 -0
- package/scripts/check_release_trunk_sync.py +152 -0
- package/scripts/council_cli.py +36 -5
- package/scripts/install.py +3 -3
- package/scripts/run_skill_evals.py +185 -0
- package/scripts/schemas/command.schema.json +5 -0
- package/scripts/schemas/skill.schema.json +4 -0
- package/scripts/skill_linter.py +82 -3
- package/scripts/smoke_quickstart.py +134 -0
- package/scripts/validate_decision_engine.py +124 -0
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: nextjs-patterns
|
|
3
|
+
description: "Writes Next.js App Router code — Server Components, Server Actions, RSC boundaries, route handlers, caching, and streaming — matching framework conventions and project architecture."
|
|
4
|
+
source: package
|
|
5
|
+
domain: engineering
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# nextjs-patterns
|
|
9
|
+
|
|
10
|
+
## Compatibility
|
|
11
|
+
|
|
12
|
+
- **Tested against:** Next.js `14.x` and `15.x` (App Router), React `18+` / `19+`.
|
|
13
|
+
- Pages Router is **out of scope**. On a Pages-Router project (no `app/`),
|
|
14
|
+
fall back to plain React skills; ask before introducing App Router.
|
|
15
|
+
|
|
16
|
+
## When to use
|
|
17
|
+
|
|
18
|
+
Use this skill for Next.js-specific code generation and editing on the App Router:
|
|
19
|
+
|
|
20
|
+
- Server Components (RSC) and Client Components (`"use client"`)
|
|
21
|
+
- Server Actions (`"use server"`)
|
|
22
|
+
- Route Handlers (`app/api/**/route.ts`)
|
|
23
|
+
- Layouts, templates, loading / error / not-found boundaries
|
|
24
|
+
- Data fetching with `fetch` + cache directives
|
|
25
|
+
- `revalidatePath` / `revalidateTag` invalidation
|
|
26
|
+
- Streaming and `<Suspense>` boundaries
|
|
27
|
+
- Middleware (`middleware.ts`)
|
|
28
|
+
- Metadata API (static + dynamic)
|
|
29
|
+
- Route Groups, Parallel Routes, Intercepting Routes
|
|
30
|
+
|
|
31
|
+
## When to use the analysis sibling
|
|
32
|
+
|
|
33
|
+
When the task is **understanding** how a Next.js app boots, where the
|
|
34
|
+
server/client boundary lives, what is cached vs streamed, or why a
|
|
35
|
+
hydration mismatch fires — defer to `project-analysis-nextjs` first,
|
|
36
|
+
then return here for the edit.
|
|
37
|
+
|
|
38
|
+
## Procedure: write Next.js code
|
|
39
|
+
|
|
40
|
+
1. **Confirm App Router** — `app/` directory exists; `next.config.{js,ts,mjs}` present.
|
|
41
|
+
2. **Confirm version** — `package.json` major for `next`. 14.x vs 15.x differs in
|
|
42
|
+
default caching (15.x is uncached by default for `fetch`) and in `cookies()` /
|
|
43
|
+
`headers()` being async.
|
|
44
|
+
3. **Inspect routing layout** — flat `app/` vs grouped (`app/(marketing)/`,
|
|
45
|
+
`app/(app)/`); identify shared layouts and parallel routes.
|
|
46
|
+
4. **Inspect data layer** — Server Actions vs route handlers vs external API;
|
|
47
|
+
ORM (Prisma, Drizzle) or fetch-based.
|
|
48
|
+
5. **Inspect styling** — Tailwind, CSS Modules, or styled engine; respect the
|
|
49
|
+
chosen stack, do not mix.
|
|
50
|
+
6. **Check test conventions** — Vitest / Jest + RTL for components; Playwright
|
|
51
|
+
for E2E; route-handler tests via `node` runtime.
|
|
52
|
+
|
|
53
|
+
## Server vs Client boundary
|
|
54
|
+
|
|
55
|
+
- **Server Components are the default.** Add `"use client"` only when a leaf
|
|
56
|
+
component needs state, effects, browser APIs, or event handlers.
|
|
57
|
+
- The `"use client"` boundary is **viral upward at the import graph**, but you
|
|
58
|
+
can keep a Server Component **rendered as a child** of a Client Component
|
|
59
|
+
by passing it as a prop / `children` — that pattern keeps server logic out
|
|
60
|
+
of the client bundle.
|
|
61
|
+
- Never put database access, secrets, or server-only modules inside a Client
|
|
62
|
+
Component or a file imported by one. Use `import "server-only"` at the top
|
|
63
|
+
of a server module to make leaks fail at build time.
|
|
64
|
+
- Symmetric guard: `import "client-only"` for code that must never run on the
|
|
65
|
+
server (e.g. browser-only SDKs).
|
|
66
|
+
- Props passed from Server → Client must be serializable. No functions, no
|
|
67
|
+
Dates with custom prototypes, no `Map` / `Set` — use plain JSON.
|
|
68
|
+
|
|
69
|
+
## Server Actions
|
|
70
|
+
|
|
71
|
+
- Declare with `"use server"` at the top of the file or per-function.
|
|
72
|
+
- Server Actions are **server-only RPC**; never call them from `useEffect` for
|
|
73
|
+
pure data fetching — that is what Server Components are for.
|
|
74
|
+
- Always **validate input** (zod or equivalent) at the entry of the action —
|
|
75
|
+
the caller is the client; treat it as hostile.
|
|
76
|
+
- Always **re-authorize** inside the action; do not trust client-side guards.
|
|
77
|
+
- After a mutation: call `revalidatePath()` / `revalidateTag()` or `redirect()`.
|
|
78
|
+
- Return shape: a `{ ok: true, data }` / `{ ok: false, error }` discriminated
|
|
79
|
+
union — never throw across the action boundary for expected errors.
|
|
80
|
+
- Use `useActionState` (15.x) / `useFormState` (14.x) on the client for
|
|
81
|
+
progressive enhancement; the form must work without JS.
|
|
82
|
+
|
|
83
|
+
## Route Handlers
|
|
84
|
+
|
|
85
|
+
- `app/api/**/route.ts` exports `GET`, `POST`, etc.
|
|
86
|
+
- Handlers run on the **node runtime by default**; opt into `edge` only when
|
|
87
|
+
the dependency set supports it.
|
|
88
|
+
- Read request body once: `await req.json()` or `await req.formData()`.
|
|
89
|
+
- Return `Response` / `NextResponse`. Use `NextResponse.json` for JSON +
|
|
90
|
+
consistent status codes.
|
|
91
|
+
- Authentication and rate limiting happen **inside** the handler or via
|
|
92
|
+
`middleware.ts`; do not assume any framework default.
|
|
93
|
+
- Cache behavior: route handlers are dynamic by default in 15.x. Add
|
|
94
|
+
`export const dynamic = 'force-static'` / `revalidate = N` explicitly.
|
|
95
|
+
|
|
96
|
+
## Caching and revalidation (14.x vs 15.x)
|
|
97
|
+
|
|
98
|
+
- **14.x**: `fetch` is cached by default (force-cache); opt out with
|
|
99
|
+
`{ cache: 'no-store' }` or segment-level `export const dynamic = 'force-dynamic'`.
|
|
100
|
+
- **15.x**: `fetch` is **not cached by default**; opt in with
|
|
101
|
+
`{ cache: 'force-cache' }` or `{ next: { revalidate: N } }`.
|
|
102
|
+
- Use **tag-based revalidation** for shared invalidation surface:
|
|
103
|
+
`fetch(url, { next: { tags: ['posts'] } })` then `revalidateTag('posts')`.
|
|
104
|
+
- Use `revalidatePath('/blog/[slug]', 'page')` for targeted page invalidation.
|
|
105
|
+
- Never call `revalidate*` from a Client Component — wrap it in a Server Action.
|
|
106
|
+
- `unstable_cache` / `cache` (React) wrap pure server functions for memoization
|
|
107
|
+
within a request; respect the difference between request-scoped and
|
|
108
|
+
cross-request caching.
|
|
109
|
+
|
|
110
|
+
## Data fetching patterns
|
|
111
|
+
|
|
112
|
+
- Prefer fetching in **the Server Component that uses the data**, not in a
|
|
113
|
+
layout, to allow per-route streaming.
|
|
114
|
+
- Parallel fetching: declare independent promises and `await` together —
|
|
115
|
+
avoid sequential `await` chains that block streaming.
|
|
116
|
+
- `<Suspense>` boundaries make slow data non-blocking; wrap each independent
|
|
117
|
+
data dependency in its own Suspense, not the whole page.
|
|
118
|
+
- `loading.tsx` is a default Suspense fallback for the segment; do not use it
|
|
119
|
+
as a global spinner.
|
|
120
|
+
- Avoid `useEffect` for initial data load in Client Components — fetch on the
|
|
121
|
+
server and pass props.
|
|
122
|
+
|
|
123
|
+
## Layouts, templates, error and not-found
|
|
124
|
+
|
|
125
|
+
- `layout.tsx` is a **persistent** wrapper across navigations; do not put
|
|
126
|
+
per-page logic there.
|
|
127
|
+
- `template.tsx` re-renders on every navigation; use only when a layout
|
|
128
|
+
cannot.
|
|
129
|
+
- `loading.tsx`, `error.tsx`, `not-found.tsx` are **per-segment**; nest them
|
|
130
|
+
to localize fallbacks.
|
|
131
|
+
- `error.tsx` must be a Client Component (`"use client"`); accept `error` and
|
|
132
|
+
`reset` props.
|
|
133
|
+
|
|
134
|
+
## Middleware
|
|
135
|
+
|
|
136
|
+
- `middleware.ts` at the project root runs on the **edge runtime** before a
|
|
137
|
+
request hits a route — use for auth redirects, locale negotiation, A/B.
|
|
138
|
+
- No database access from middleware; the edge runtime cannot run most node
|
|
139
|
+
drivers. Use a session cookie + lightweight verification.
|
|
140
|
+
- `matcher` config narrows which paths invoke it — never let middleware run
|
|
141
|
+
on every asset.
|
|
142
|
+
|
|
143
|
+
## Metadata, performance, env
|
|
144
|
+
|
|
145
|
+
- Metadata: static `export const metadata`; dynamic `generateMetadata()`.
|
|
146
|
+
`generateStaticParams` for static dynamic-segment generation.
|
|
147
|
+
- `next/image`, `next/font`, `next/dynamic` for images, fonts, code-split
|
|
148
|
+
Client Components — never bare `<img>`, CSS `@import` Google Fonts, or
|
|
149
|
+
unguarded heavy imports.
|
|
150
|
+
- A single `"use client"` near the top of a tree pulls the subtree into the
|
|
151
|
+
client bundle — keep the boundary at the leaf.
|
|
152
|
+
- Env: server-only `DATABASE_URL` etc.; client-exposed must be prefixed
|
|
153
|
+
`NEXT_PUBLIC_*` and is NOT secret. Validate env at boot (zod) and import
|
|
154
|
+
the validated object — never `process.env` ad hoc.
|
|
155
|
+
|
|
156
|
+
## Output format
|
|
157
|
+
|
|
158
|
+
1. Next.js code following App Router conventions and the project's existing layout.
|
|
159
|
+
2. All related files (page, layout, server action, route handler, schema, test) as needed.
|
|
160
|
+
3. When a cache surface changes — point at the invalidation call (`revalidateTag` / `revalidatePath`).
|
|
161
|
+
|
|
162
|
+
## Do NOT
|
|
163
|
+
|
|
164
|
+
- Do NOT add `"use client"` to a file that does not need it — it pulls the
|
|
165
|
+
subtree into the client bundle.
|
|
166
|
+
- Do NOT import server modules (db client, secrets) from a Client Component
|
|
167
|
+
file — even transitively. Guard with `import "server-only"`.
|
|
168
|
+
- Do NOT call Server Actions from `useEffect` to fetch data — fetch on the server.
|
|
169
|
+
- Do NOT throw across a Server Action boundary for expected errors — return a
|
|
170
|
+
result union.
|
|
171
|
+
- Do NOT trust client-side authorization in a Server Action or route handler —
|
|
172
|
+
re-check.
|
|
173
|
+
- Do NOT mutate without revalidating — stale UI is a class of bug, not a design.
|
|
174
|
+
- Do NOT mix Pages Router and App Router patterns in one feature — pick one.
|
|
175
|
+
- Do NOT assume 14.x caching defaults on 15.x; verify the major before reasoning about cache.
|
|
176
|
+
|
|
177
|
+
## Gotcha
|
|
178
|
+
|
|
179
|
+
- **15.x async APIs**: `cookies()`, `headers()`, `params`, `searchParams` are
|
|
180
|
+
**async** in 15.x. Code that ran on 14.x will silently misbehave (Promise
|
|
181
|
+
rendered as an object) until awaited.
|
|
182
|
+
- **Hydration mismatch**: rendering `Date.now()`, `Math.random()`, or
|
|
183
|
+
locale-dependent strings without `suppressHydrationWarning` or a Client
|
|
184
|
+
boundary causes a hydration error.
|
|
185
|
+
- **`"use client"` is not opt-in for hooks**: it is required for any file
|
|
186
|
+
using `useState`, `useEffect`, `useRef`, or browser globals.
|
|
187
|
+
- **Server Actions and forms**: a Server Action used as a form action must
|
|
188
|
+
accept `FormData`. Mixing `FormData` and typed args breaks progressive
|
|
189
|
+
enhancement.
|
|
190
|
+
- **Cache lies during dev**: dev mode ignores most cache directives. Verify
|
|
191
|
+
caching behavior in a production build (`next build && next start`).
|
|
192
|
+
- **`revalidatePath` requires the route group syntax** for parallel/dynamic
|
|
193
|
+
segments — bare paths silently miss.
|
|
194
|
+
- **Edge runtime ≠ Node**: most npm packages with native deps or Node-only
|
|
195
|
+
APIs (`fs`, `crypto.createHash`) fail at the edge. Pin runtime per route.
|
|
196
|
+
|
|
197
|
+
## Auto-trigger keywords
|
|
198
|
+
|
|
199
|
+
- Next.js / App Router · Server Component (RSC) · Client Component (`"use client"`)
|
|
200
|
+
- Server Action (`"use server"`) · Route Handler (`app/api`) · `middleware.ts`
|
|
201
|
+
- `revalidatePath` / `revalidateTag` / `unstable_cache`
|
|
202
|
+
- `next/image` / `next/font` / `next/dynamic`
|
|
203
|
+
- `layout.tsx` / `loading.tsx` / `error.tsx` / `not-found.tsx`
|
|
@@ -3,6 +3,7 @@ name: skill-writing
|
|
|
3
3
|
description: "Use when deciding 'should this be a skill or a rule?', creating/improving/reviewing agent skills, SKILL.md frontmatter, or procedure sections — even without saying 'skill-writing'."
|
|
4
4
|
source: project
|
|
5
5
|
domain: process
|
|
6
|
+
meta_skill: true
|
|
6
7
|
---
|
|
7
8
|
|
|
8
9
|
# skill-writing
|
|
@@ -62,22 +63,25 @@ Ask: **"Does the model need this to do its job correctly?"**
|
|
|
62
63
|
|
|
63
64
|
### Skills and commands share the `.claude/skills/` namespace
|
|
64
65
|
|
|
65
|
-
Skills
|
|
66
|
-
|
|
67
|
-
`.claude/skills/` (`scripts/compress.py` →
|
|
68
|
-
`generate_claude_commands`). Claude treats
|
|
69
|
-
skills.
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
*
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
66
|
+
Skills in `.agent-src.uncompressed/skills/{name}/SKILL.md` AND commands in
|
|
67
|
+
`.agent-src.uncompressed/commands/{name}.md` both project into
|
|
68
|
+
`.claude/skills/` (see `scripts/compress.py` →
|
|
69
|
+
`generate_claude_skills` + `generate_claude_commands`). Claude treats
|
|
70
|
+
the whole directory as native skills.
|
|
71
|
+
|
|
72
|
+
Implications for skill authors:
|
|
73
|
+
|
|
74
|
+
* If a same-name command already exists, the skill takes priority and
|
|
75
|
+
the command is skipped (`generate_claude_commands` honors this).
|
|
76
|
+
Don't reuse a command's slug for a skill unless the command should
|
|
77
|
+
retire.
|
|
78
|
+
* Both artifacts compete on `description` for routing. A weak skill
|
|
79
|
+
description is shadowed by a stronger same-domain command — and vice
|
|
80
|
+
versa. Make trigger phrasing precise (§ 1b below).
|
|
81
|
+
* When the workflow has both a "user types `/foo`" path AND a "model
|
|
82
|
+
picks this up from intent" path, author the skill first and let the
|
|
83
|
+
command delegate (`skills:` frontmatter). Two artifacts with the same
|
|
84
|
+
trigger surface fight each other in the router.
|
|
81
85
|
|
|
82
86
|
### When "Nothing" is the right answer
|
|
83
87
|
|
|
@@ -263,6 +267,87 @@ Example:
|
|
|
263
267
|
* K7: Created with analysis (not blind, expected behavior defined)
|
|
264
268
|
* Size: Within limits (see size-and-scope guideline)
|
|
265
269
|
|
|
270
|
+
### 7. Run + iterate evals (quantitative loop)
|
|
271
|
+
|
|
272
|
+
Triggers (`evals/triggers.json`) check **routing**. A separate
|
|
273
|
+
`evals/evals.json` checks **behavior** — does the skill make the agent
|
|
274
|
+
produce a better answer than baseline? Add this layer for any skill
|
|
275
|
+
where the procedure has measurable output (commands, artifacts,
|
|
276
|
+
structured text). Skip for evergreen heuristics with no falsifiable
|
|
277
|
+
output (e.g. `direct-answers`, `language-and-tone`) unless the user
|
|
278
|
+
asks for it.
|
|
279
|
+
|
|
280
|
+
**Workspace layout** (all under `.gitignore`):
|
|
281
|
+
|
|
282
|
+
```
|
|
283
|
+
.agent-src.uncompressed/skills/{name}/evals/
|
|
284
|
+
triggers.json # tracked — routing eval (§ 1c)
|
|
285
|
+
evals.json # tracked — behavior eval definitions
|
|
286
|
+
runs/ # gitignored — per-iteration outputs
|
|
287
|
+
{timestamp}-baseline/ # sub-agent run without the skill
|
|
288
|
+
{timestamp}-with-skill/ # sub-agent run with the skill
|
|
289
|
+
{timestamp}-benchmark.json
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
**`evals.json` shape** — 3–10 scenarios, each with prompt + grading
|
|
293
|
+
rubric:
|
|
294
|
+
|
|
295
|
+
```json
|
|
296
|
+
{
|
|
297
|
+
"skill": "{name}",
|
|
298
|
+
"scenarios": [
|
|
299
|
+
{
|
|
300
|
+
"id": "happy-path",
|
|
301
|
+
"prompt": "<full user-shaped task that exercises the skill>",
|
|
302
|
+
"assertions": [
|
|
303
|
+
{"kind": "contains", "value": "<expected substring in output>"},
|
|
304
|
+
{"kind": "file_exists", "path": "<artifact path the skill should create>"},
|
|
305
|
+
{"kind": "rubric", "criterion": "<one-line judgement, e.g. 'output includes a numbered procedure'>"}
|
|
306
|
+
]
|
|
307
|
+
}
|
|
308
|
+
]
|
|
309
|
+
}
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
`contains` / `file_exists` grade deterministically. `rubric` items grade
|
|
313
|
+
via a fresh sub-agent reading the output against the criterion — keep
|
|
314
|
+
each criterion to one falsifiable sentence.
|
|
315
|
+
|
|
316
|
+
**Loop** (orchestrated by `scripts/run_skill_evals.py`):
|
|
317
|
+
|
|
318
|
+
1. **Scaffold** — `python3 scripts/run_skill_evals.py scaffold {skill}`
|
|
319
|
+
creates `runs/{timestamp}-{baseline,with-skill}/` and seeds each
|
|
320
|
+
scenario's `meta.json`.
|
|
321
|
+
2. **Baseline run** — spawn one sub-agent per scenario **without** the
|
|
322
|
+
skill loaded. Capture stdout + any artifacts into
|
|
323
|
+
`runs/{timestamp}-baseline/{scenario-id}/`.
|
|
324
|
+
3. **With-skill run** — same scenarios, same sub-agent harness, **with**
|
|
325
|
+
the skill loaded. Capture into `runs/{timestamp}-with-skill/{scenario-id}/`.
|
|
326
|
+
4. **Grade** — for each scenario, write a `grade.json` file with
|
|
327
|
+
per-assertion pass/fail. Deterministic assertions auto-grade;
|
|
328
|
+
rubric assertions need a grader sub-agent.
|
|
329
|
+
5. **Aggregate** — `python3 scripts/run_skill_evals.py aggregate {skill}
|
|
330
|
+
--run {timestamp}` produces `runs/{timestamp}-benchmark.json` with
|
|
331
|
+
pass-rate, timing, token deltas baseline-vs-with-skill.
|
|
332
|
+
6. **Report** — `python3 scripts/run_skill_evals.py report {skill}
|
|
333
|
+
--run {timestamp}` prints the diff. Iterate on the skill body
|
|
334
|
+
until `with-skill` outperforms `baseline` on every scenario.
|
|
335
|
+
|
|
336
|
+
The script ships with sub-agent spawning **stubbed** — the orchestration
|
|
337
|
+
layer is per-environment (Claude Code, Augment, council). Implement
|
|
338
|
+
the spawn function once for your environment, the rest of the loop
|
|
339
|
+
(aggregate / report / scaffold) works out of the box.
|
|
340
|
+
|
|
341
|
+
**Exit criterion** — every scenario passes with-skill, at least one
|
|
342
|
+
fails baseline (proves the skill earns its slot). Commit the
|
|
343
|
+
`evals.json` alongside the skill; never commit `runs/`.
|
|
344
|
+
|
|
345
|
+
Neighbors:
|
|
346
|
+
* `description-assist` — iterate on the trigger phrasing
|
|
347
|
+
* `skill-reviewer` — structural 7-Killers audit
|
|
348
|
+
* `lint-skills` — static checks (frontmatter, sections, size)
|
|
349
|
+
* `skill-improvement-pipeline` — production-learning capture
|
|
350
|
+
|
|
266
351
|
## Output format
|
|
267
352
|
|
|
268
353
|
1. Complete SKILL.md file
|
|
@@ -17,7 +17,7 @@ Do NOT use when:
|
|
|
17
17
|
|
|
18
18
|
## Procedure: Write raw SQL
|
|
19
19
|
|
|
20
|
-
1. **
|
|
20
|
+
1. **Inspect call site & choose approach** — identify every dynamic value flowing into the query, then pick: query builder when possible. Raw SQL only when query builder can't express the query.
|
|
21
21
|
2. **Parameterize** — Every variable must use `?` binding or named `:param`. Never interpolate PHP variables into SQL strings.
|
|
22
22
|
3. **Use MariaDB syntax** — Not PostgreSQL or MSSQL. Check `php/sql.md` for MariaDB-specific patterns.
|
|
23
23
|
4. **Verify** — Run EXPLAIN on complex queries. Check that no PHP interpolation (`"$var"`, `'{$var}'`) appears in SQL.
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: symfony-workflow
|
|
3
|
+
description: "Writes Symfony code following framework conventions, container wiring, and modern best practices for controllers, services, bundles, Messenger, Doctrine, security, and console commands."
|
|
4
|
+
source: package
|
|
5
|
+
domain: engineering
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# symfony-workflow
|
|
9
|
+
|
|
10
|
+
## When to use
|
|
11
|
+
|
|
12
|
+
Use this skill for all Symfony-specific code generation and editing tasks, especially when working with:
|
|
13
|
+
|
|
14
|
+
- Controllers (annotated / attribute-routed)
|
|
15
|
+
- Request listeners / event subscribers
|
|
16
|
+
- Services and Dependency Injection (`services.yaml`)
|
|
17
|
+
- Forms and validators
|
|
18
|
+
- Doctrine entities, repositories, and migrations
|
|
19
|
+
- Security: firewalls, voters, authenticators
|
|
20
|
+
- Messenger handlers and transports
|
|
21
|
+
- Console commands
|
|
22
|
+
- Bundles, compiler passes, and tagged services
|
|
23
|
+
- Twig templates and view logic
|
|
24
|
+
|
|
25
|
+
This skill extends the base `php-coder` skill and applies Symfony conventions on top of the project's general PHP rules.
|
|
26
|
+
|
|
27
|
+
## When to use the analysis sibling
|
|
28
|
+
|
|
29
|
+
When the task is **understanding** how a Symfony app boots, wires its container, routes requests, or fails at runtime — defer to `project-analysis-symfony` first, then return here for the edit. This skill assumes the kernel/container layout is already known.
|
|
30
|
+
|
|
31
|
+
## Procedure: write Symfony code
|
|
32
|
+
|
|
33
|
+
→ **First apply the `php-coder` skill** for general PHP rules.
|
|
34
|
+
|
|
35
|
+
Then add these **Symfony-specific** checks:
|
|
36
|
+
|
|
37
|
+
1. **Confirm Symfony** — `bin/console` exists, `composer.json` lists `symfony/framework-bundle`.
|
|
38
|
+
2. **Confirm version** — `composer.lock` for the framework-bundle major. 5.x → 6.x → 7.x differs in attribute routing, voter signatures, and Messenger DSN shape.
|
|
39
|
+
3. **Inspect app structure** — standard, modular (`src/Module/<Name>/`), or DDD-style. Do not enforce a layout the project does not use.
|
|
40
|
+
4. **Check config layout** — `config/packages/<env>/`, `services.yaml` autowiring vs explicit bindings, `config/bundles.php`.
|
|
41
|
+
5. **Check test conventions** — PHPUnit/Codeception; unit vs integration vs functional split.
|
|
42
|
+
|
|
43
|
+
## Core Symfony principles
|
|
44
|
+
|
|
45
|
+
- Follow Symfony conventions unless the project explicitly does otherwise.
|
|
46
|
+
- Keep controllers thin — delegate to services.
|
|
47
|
+
- Rely on autowiring + autoconfigure unless the project has explicit bindings.
|
|
48
|
+
- Prefer attributes over annotations on 6.x+; keep annotations only if the codebase still uses them.
|
|
49
|
+
- Use service IDs by FQCN — `App\Service\Foo`, not custom string IDs.
|
|
50
|
+
- Services are private by default; do not flip `public: true` to make tests pass.
|
|
51
|
+
- Do not bypass the container with `new` on classes that have collaborators.
|
|
52
|
+
|
|
53
|
+
## HTTP layer rules
|
|
54
|
+
|
|
55
|
+
- Controllers:
|
|
56
|
+
- extend `AbstractController` only when the project does
|
|
57
|
+
- accept `Request` or a DTO; delegate business logic; return a `Response` variant
|
|
58
|
+
- Use `#[Route]` attributes on 6.x+; YAML routes only where the project already does.
|
|
59
|
+
- Use `#[MapRequestPayload]` / `#[MapQueryString]` (7.x+) for request DTOs when the project uses them.
|
|
60
|
+
- Validate via Symfony Validator on the DTO, not inline in the controller.
|
|
61
|
+
- Use `ParamConverter` / argument resolvers for entities only when the project uses them.
|
|
62
|
+
|
|
63
|
+
## Validation rules
|
|
64
|
+
|
|
65
|
+
- Symfony Validator with constraints on DTOs / entities.
|
|
66
|
+
- Prefer attribute constraints (`#[Assert\NotBlank]`, `#[Assert\Email]`) on 6.x+.
|
|
67
|
+
- Render errors from `ConstraintViolationListInterface` — never compose error arrays by hand.
|
|
68
|
+
- Validation is declarative; do not put domain validation in entity setters.
|
|
69
|
+
|
|
70
|
+
## Service layer and DI rules
|
|
71
|
+
|
|
72
|
+
- One responsibility per service; constructor injection.
|
|
73
|
+
- Interfaces when there are multiple implementations or the boundary is mocked.
|
|
74
|
+
- Tagged services for collecting implementations — `#[AutoconfigureTag]` or YAML tags, never an injected array of FQCNs.
|
|
75
|
+
- Decorators via `#[AsDecorator]` (6.1+); respect priority.
|
|
76
|
+
- Compiler passes only when wiring cannot be expressed via attributes/YAML.
|
|
77
|
+
- Do not call `Container::get` in application code.
|
|
78
|
+
|
|
79
|
+
## Routing rules
|
|
80
|
+
|
|
81
|
+
- Follow the existing organization — attributes on controllers, or YAML in `config/routes/`.
|
|
82
|
+
- Route names: `<resource>_<action>` (`user_show`, `invoice_list`).
|
|
83
|
+
- `#[IsGranted]`, `#[RateLimit]` at the route level, not inside the controller body.
|
|
84
|
+
- `requirements:` for path parameter constraints; do not validate in the controller.
|
|
85
|
+
|
|
86
|
+
## Response rules
|
|
87
|
+
|
|
88
|
+
- Match the project's response style: Twig, `JsonResponse`, API Platform, or redirects with flash.
|
|
89
|
+
- For APIs: consistent status codes; `ConstraintViolationList` → `application/problem+json`; DTOs / serializer groups, not raw entities.
|
|
90
|
+
- Do not return entities directly unless the project consistently does that.
|
|
91
|
+
|
|
92
|
+
## Messenger and async work
|
|
93
|
+
|
|
94
|
+
- Messenger for async/deferred work; one message class per intent.
|
|
95
|
+
- Handlers: `MessageHandlerInterface` (5.x) or `#[AsMessageHandler]` (6.x+).
|
|
96
|
+
- Route via `framework.messenger.routing` in `config/packages/messenger.yaml`.
|
|
97
|
+
- Configure `failure_transport` explicitly — without it, failed messages disappear.
|
|
98
|
+
- Pass IDs, not entities; the consumer re-fetches.
|
|
99
|
+
|
|
100
|
+
## Events and subscribers
|
|
101
|
+
|
|
102
|
+
- `#[AsEventListener]` (6.1+) or `EventSubscriberInterface` — match the project's convention.
|
|
103
|
+
- Past-tense event names (`UserRegistered`, `OrderPaid`); one side-effect per subscriber.
|
|
104
|
+
- Respect priority on `kernel.request` / `kernel.response` — wrong priority is a frequent bug source.
|
|
105
|
+
|
|
106
|
+
## Security, voters, authorization
|
|
107
|
+
|
|
108
|
+
- One firewall per surface in `config/packages/security.yaml` (main, API, admin).
|
|
109
|
+
- Voters for object-level permissions; never role checks in templates or controllers.
|
|
110
|
+
- `#[IsGranted]` on actions; `$this->isGranted()` only when the result drives downstream logic.
|
|
111
|
+
- Stateless APIs: token-based authenticator, not form-login.
|
|
112
|
+
|
|
113
|
+
## Config and environment
|
|
114
|
+
|
|
115
|
+
- Read via `ParameterBagInterface` or `#[Autowire(param: ...)]` — never `$_ENV` directly.
|
|
116
|
+
- New env vars in `.env` (+ `.env.test`); production values in deployment config.
|
|
117
|
+
- Bundle config under `config/packages/<bundle>.yaml`; env overrides under `config/packages/<env>/`.
|
|
118
|
+
|
|
119
|
+
## Doctrine and persistence
|
|
120
|
+
|
|
121
|
+
- Doctrine ORM unless the project uses DBAL/raw SQL by convention.
|
|
122
|
+
- Repositories for non-trivial queries; no inline QueryBuilder in controllers/services.
|
|
123
|
+
- N+1 awareness: fetch joins via `addSelect` or `EAGER` when always needed.
|
|
124
|
+
- Transactions via `EntityManager::wrapInTransaction()` for multi-write atomicity.
|
|
125
|
+
- Lifecycle hooks (`PreFlush`, `PostUpdate`) — no domain logic there unless the project already does.
|
|
126
|
+
|
|
127
|
+
## Migrations
|
|
128
|
+
|
|
129
|
+
- Generate via `doctrine:migrations:diff`; review before commit.
|
|
130
|
+
- Reversible — implement `up()` and `down()`.
|
|
131
|
+
- One concern per migration; destructive prod changes split into expand → migrate → contract.
|
|
132
|
+
|
|
133
|
+
## Twig
|
|
134
|
+
|
|
135
|
+
- Templates are dumb — presentation only; pre-computed view models from the controller/service.
|
|
136
|
+
- Reuse via `{% extends %}` / `{% include %}` / macros.
|
|
137
|
+
- Auto-escape on; `|raw` only when content is provably safe.
|
|
138
|
+
|
|
139
|
+
## Bundles and compiler passes
|
|
140
|
+
|
|
141
|
+
- Bundles are for reusable, redistributable code — not "another folder".
|
|
142
|
+
- Compiler passes only when wiring cannot be expressed via attributes/YAML.
|
|
143
|
+
|
|
144
|
+
## Console commands
|
|
145
|
+
|
|
146
|
+
- `#[AsCommand]` (6.x+); one command class per intent; constructor injection.
|
|
147
|
+
- Long-running: `--limit`, `--time-limit`, graceful `SIGTERM` shutdown.
|
|
148
|
+
- Output via `OutputInterface` — never `echo`.
|
|
149
|
+
|
|
150
|
+
## Output format
|
|
151
|
+
|
|
152
|
+
1. Symfony code following framework conventions and project architecture.
|
|
153
|
+
2. All related files (controller, service, DTO, repository, test, config) as needed.
|
|
154
|
+
3. Schema changes — migration file plus updated entity/mapping.
|
|
155
|
+
|
|
156
|
+
## Do NOT
|
|
157
|
+
|
|
158
|
+
- Business logic in controllers, entities, listeners, or Twig.
|
|
159
|
+
- Bypass the container with `new` on classes with collaborators.
|
|
160
|
+
- `$_ENV` / `$_SERVER` direct access — go through the parameter bag.
|
|
161
|
+
- Return Doctrine entities from an API endpoint — use DTOs or serializer groups.
|
|
162
|
+
- Silently swallow Messenger failures — route to a failure transport.
|
|
163
|
+
- Flip services `public: true` to make tests pass — use the test container.
|
|
164
|
+
- Pass entities through Messenger — pass IDs.
|
|
165
|
+
- Mix attribute and YAML routing for the same controller surface.
|
|
166
|
+
|
|
167
|
+
## Gotcha
|
|
168
|
+
|
|
169
|
+
- Autowiring fails silently when two implementations exist without explicit binding — read the error, don't just flip `public: true`.
|
|
170
|
+
- `#[IsGranted]` is a no-op if the controller is not a service (autoconfigure handles it by default).
|
|
171
|
+
- Messenger `failure_transport` is opt-in; without it, failures vanish.
|
|
172
|
+
- Compiled container changes need `cache:clear` in `prod` before debugging "config not applied".
|
|
173
|
+
- Symfony 7.x removed deprecated APIs — verify `composer.lock` before assuming 6.x patterns work.
|
|
@@ -23,6 +23,7 @@ from .hooks.builtin import (
|
|
|
23
23
|
MemoryVisibilityHook,
|
|
24
24
|
StateShapeValidationHook,
|
|
25
25
|
TraceHook,
|
|
26
|
+
build_decision_gate_hook,
|
|
26
27
|
)
|
|
27
28
|
from .hooks.settings import HookSettings, load_hook_settings
|
|
28
29
|
|
|
@@ -58,6 +59,9 @@ def _build_hook_registry(args: argparse.Namespace) -> HookRegistry:
|
|
|
58
59
|
DirectiveSetGuardHook().register(registry)
|
|
59
60
|
if settings.decision_trace:
|
|
60
61
|
DecisionTraceHook().register(registry)
|
|
62
|
+
gate_hook = build_decision_gate_hook(settings.decision_engine)
|
|
63
|
+
if gate_hook is not None:
|
|
64
|
+
gate_hook.register(registry)
|
|
61
65
|
if settings.memory_visibility:
|
|
62
66
|
MemoryVisibilityHook(
|
|
63
67
|
cost_profile=settings.cost_profile,
|
|
@@ -13,6 +13,7 @@ from __future__ import annotations
|
|
|
13
13
|
|
|
14
14
|
from .chat_history_append import ChatHistoryAppendHook
|
|
15
15
|
from .chat_history_halt_append import ChatHistoryHaltAppendHook
|
|
16
|
+
from .decision_gate import DecisionGateHook, build_decision_gate_hook
|
|
16
17
|
from .decision_trace import DecisionTraceHook
|
|
17
18
|
from .directive_set_guard import DirectiveSetGuardHook
|
|
18
19
|
from .halt_surface_audit import HaltSurfaceAuditHook
|
|
@@ -23,10 +24,12 @@ from .trace import TraceHook
|
|
|
23
24
|
__all__ = [
|
|
24
25
|
"ChatHistoryAppendHook",
|
|
25
26
|
"ChatHistoryHaltAppendHook",
|
|
27
|
+
"DecisionGateHook",
|
|
26
28
|
"DecisionTraceHook",
|
|
27
29
|
"DirectiveSetGuardHook",
|
|
28
30
|
"HaltSurfaceAuditHook",
|
|
29
31
|
"MemoryVisibilityHook",
|
|
30
32
|
"StateShapeValidationHook",
|
|
31
33
|
"TraceHook",
|
|
34
|
+
"build_decision_gate_hook",
|
|
32
35
|
]
|