@event4u/agent-config 2.10.0 → 2.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 (82) hide show
  1. package/.agent-src/commands/agents.md +1 -0
  2. package/.agent-src/commands/challenge-me.md +1 -0
  3. package/.agent-src/commands/chat-history.md +1 -0
  4. package/.agent-src/commands/context.md +1 -0
  5. package/.agent-src/commands/council.md +1 -0
  6. package/.agent-src/commands/feature.md +1 -0
  7. package/.agent-src/commands/fix.md +1 -0
  8. package/.agent-src/commands/grill-me.md +1 -0
  9. package/.agent-src/commands/judge.md +1 -0
  10. package/.agent-src/commands/memory.md +1 -0
  11. package/.agent-src/commands/module.md +1 -0
  12. package/.agent-src/commands/onboard.md +32 -4
  13. package/.agent-src/commands/optimize.md +1 -0
  14. package/.agent-src/commands/override.md +1 -0
  15. package/.agent-src/commands/roadmap.md +1 -0
  16. package/.agent-src/commands/tests.md +1 -0
  17. package/.agent-src/skills/nextjs-patterns/SKILL.md +203 -0
  18. package/.agent-src/skills/symfony-workflow/SKILL.md +173 -0
  19. package/.agent-src/templates/scripts/work_engine/hook_bootstrap.py +4 -0
  20. package/.agent-src/templates/scripts/work_engine/hooks/builtin/__init__.py +3 -0
  21. package/.agent-src/templates/scripts/work_engine/hooks/builtin/decision_gate.py +162 -0
  22. package/.agent-src/templates/scripts/work_engine/hooks/settings.py +24 -6
  23. package/.agent-src/templates/scripts/work_engine/scoring/decision_engine.py +351 -0
  24. package/.claude-plugin/marketplace.json +3 -1
  25. package/CHANGELOG.md +37 -0
  26. package/README.md +37 -8
  27. package/config/agent-settings.template.yml +57 -0
  28. package/docs/architecture.md +1 -1
  29. package/docs/contracts/STABILITY.md +16 -0
  30. package/docs/contracts/adr-chat-history-split.md +1 -0
  31. package/docs/contracts/adr-forecast-construction-shape.md +1 -0
  32. package/docs/contracts/adr-gtm-context-spine.md +1 -0
  33. package/docs/contracts/adr-level-6-productization.md +147 -0
  34. package/docs/contracts/adr-settings-sync-engine.md +1 -0
  35. package/docs/contracts/adr-wing4-context-spine.md +1 -0
  36. package/docs/contracts/agent-memory-contract.md +1 -0
  37. package/docs/contracts/agents-md-tech-stack.md +1 -0
  38. package/docs/contracts/audit-log-v1.md +1 -0
  39. package/docs/contracts/command-clusters.md +1 -0
  40. package/docs/contracts/command-surface-tiers.md +1 -0
  41. package/docs/contracts/context-paths.md +1 -0
  42. package/docs/contracts/cost-profile-defaults.md +105 -0
  43. package/docs/contracts/cross-wing-handoff.md +1 -0
  44. package/docs/contracts/decision-engine-gates.md +115 -0
  45. package/docs/contracts/decision-trace-v1.md +1 -0
  46. package/docs/contracts/file-ownership-matrix.md +1 -0
  47. package/docs/contracts/hook-architecture-v1.md +1 -0
  48. package/docs/contracts/implement-ticket-flow.md +1 -0
  49. package/docs/contracts/installed-tools-lockfile.md +1 -0
  50. package/docs/contracts/kernel-membership.md +1 -0
  51. package/docs/contracts/linear-ai-rules-inclusion.md +1 -0
  52. package/docs/contracts/linear-ai-three-layers.md +1 -0
  53. package/docs/contracts/linter-structural-model.md +1 -0
  54. package/docs/contracts/load-context-budget-model.md +1 -0
  55. package/docs/contracts/load-context-schema.md +1 -0
  56. package/docs/contracts/memory-visibility-v1.md +1 -0
  57. package/docs/contracts/one-off-script-lifecycle.md +1 -0
  58. package/docs/contracts/orchestration-dsl-v1.md +1 -0
  59. package/docs/contracts/package-self-orientation.md +1 -0
  60. package/docs/contracts/persona-schema.md +1 -0
  61. package/docs/contracts/release-trunk-sync.md +104 -0
  62. package/docs/contracts/roadmap-complexity-standard.md +1 -0
  63. package/docs/contracts/rule-classification.md +1 -0
  64. package/docs/contracts/rule-interactions.md +26 -0
  65. package/docs/contracts/rule-priority-hierarchy.md +1 -0
  66. package/docs/contracts/rule-router.md +1 -0
  67. package/docs/contracts/settings-sync-yaml-subset.md +1 -0
  68. package/docs/contracts/skill-domains.md +1 -0
  69. package/docs/contracts/tier-3-contrib-plugin.md +1 -0
  70. package/docs/contracts/ui-stack-extension.md +1 -0
  71. package/docs/contracts/ui-track-flow.md +1 -0
  72. package/docs/customization.md +1 -1
  73. package/docs/getting-started.md +3 -1
  74. package/docs/installation.md +8 -6
  75. package/package.json +1 -1
  76. package/scripts/check_beta_review_markers.py +127 -0
  77. package/scripts/check_release_trunk_sync.py +152 -0
  78. package/scripts/install.py +3 -3
  79. package/scripts/schemas/command.schema.json +5 -0
  80. package/scripts/skill_linter.py +11 -2
  81. package/scripts/smoke_quickstart.py +134 -0
  82. package/scripts/validate_decision_engine.py +124 -0
@@ -3,6 +3,7 @@ name: agents
3
3
  tier: 1
4
4
  description: Agent-layer orchestrator — routes to init, optimize, audit. Covers AGENTS.md and its multi-tool stubs (CLAUDE.md, GEMINI.md, copilot-instructions.md, .cursorrules).
5
5
  cluster: agents
6
+ type: orchestrator
6
7
  disable-model-invocation: true
7
8
  suggestion:
8
9
  eligible: true
@@ -3,6 +3,7 @@ name: challenge-me
3
3
  tier: 2
4
4
  description: Challenge-me orchestrator — routes to vision, with-docs
5
5
  cluster: challenge-me
6
+ type: orchestrator
6
7
  disable-model-invocation: true
7
8
  suggestion:
8
9
  eligible: true
@@ -3,6 +3,7 @@ name: chat-history
3
3
  tier: 2
4
4
  description: Chat-history orchestrator — routes to show, import, learn
5
5
  cluster: chat-history
6
+ type: orchestrator
6
7
  disable-model-invocation: true
7
8
  suggestion:
8
9
  eligible: true
@@ -3,6 +3,7 @@ name: context
3
3
  tier: 2
4
4
  description: Context orchestrator — routes to create, refactor
5
5
  cluster: context
6
+ type: orchestrator
6
7
  disable-model-invocation: true
7
8
  suggestion:
8
9
  eligible: true
@@ -3,6 +3,7 @@ name: council
3
3
  tier: 1
4
4
  description: Council orchestrator — routes to default, pr, design, optimize
5
5
  cluster: council
6
+ type: orchestrator
6
7
  disable-model-invocation: true
7
8
  suggestion:
8
9
  eligible: true
@@ -3,6 +3,7 @@ name: feature
3
3
  tier: 1
4
4
  description: Feature orchestrator — routes to explore, plan, refactor, roadmap, dev
5
5
  cluster: feature
6
+ type: orchestrator
6
7
  disable-model-invocation: true
7
8
  suggestion:
8
9
  eligible: true
@@ -3,6 +3,7 @@ name: fix
3
3
  tier: 1
4
4
  description: Fix orchestrator — routes to ci, references, portability, seeder, pr-comments, pr-bot-comments, pr-developer-comments
5
5
  cluster: fix
6
+ type: orchestrator
6
7
  disable-model-invocation: true
7
8
  suggestion:
8
9
  eligible: true
@@ -3,6 +3,7 @@ name: grill-me
3
3
  tier: 2
4
4
  description: Alias for /challenge-me — interactive grill-style interview that sharpens a fuzzy plan/idea into a copyable Markdown pitch
5
5
  cluster: challenge-me
6
+ type: orchestrator
6
7
  disable-model-invocation: true
7
8
  suggestion:
8
9
  eligible: true
@@ -3,6 +3,7 @@ name: judge
3
3
  tier: 1
4
4
  description: Judge orchestrator — routes to solo, steps, on-diff
5
5
  cluster: judge
6
+ type: orchestrator
6
7
  disable-model-invocation: true
7
8
  suggestion:
8
9
  eligible: true
@@ -3,6 +3,7 @@ name: memory
3
3
  tier: 1
4
4
  description: Memory orchestrator — routes to add, load, mine-session, promote, propose
5
5
  cluster: memory
6
+ type: orchestrator
6
7
  disable-model-invocation: true
7
8
  suggestion:
8
9
  eligible: true
@@ -3,6 +3,7 @@ name: module
3
3
  tier: 2
4
4
  description: Module orchestrator — routes to create, explore
5
5
  cluster: module
6
+ type: orchestrator
6
7
  disable-model-invocation: true
7
8
  suggestion:
8
9
  eligible: true
@@ -153,11 +153,12 @@ rtk post-install steps (telemetry off, init --global) per
153
153
  ### 7. Confirm `cost_profile` and learning loop
154
154
 
155
155
  Read current `cost_profile` and `pipelines.skill_improvement` values.
156
- Present plainly (sensible defaults from template — `minimal` +
157
- `skill_improvement: true`):
156
+ Present plainly (sensible defaults from template — `balanced` +
157
+ `skill_improvement: true`; rationale in
158
+ [`docs/contracts/cost-profile-defaults.md`](../docs/contracts/cost-profile-defaults.md)):
158
159
 
159
160
  ```
160
- > Cost profile: {current} (minimal by default — includes the learning loop)
161
+ > Cost profile: {current} (balanced by default — kernel + tier-1 auto-rules)
161
162
  > Learning loop (skill_improvement): {current} (true by default)
162
163
  >
163
164
  > 1. Keep defaults — recommended
@@ -236,7 +237,34 @@ directly — the agent follows the merge rules in `layered-settings` when
236
237
  you ask it to change a value.
237
238
  ```
238
239
 
239
- ### 11. Maintainer-only feature pointer
240
+ ### 11. Quickstart pointer — next command after onboarding
241
+
242
+ Print next-action block so developer does **not** have to re-find README
243
+ to start work. One screen, no question, no prompt:
244
+
245
+ ```
246
+ 🚀 Next step — your first real task
247
+
248
+ Try one of these from the same chat:
249
+
250
+ /work "your first real task"
251
+ Free-form prompt — agent refines, plans, implements, tests,
252
+ verifies, reports. A decision_result entry lands in agents/state/
253
+ confirming the work-engine ran end-to-end.
254
+
255
+ /implement-ticket PROJ-123
256
+ Ticket-driven flow — pulls Jira/Linear context, runs same
257
+ refine → memory → analyze → plan → implement → test → verify
258
+ → report sequence, halts on ambiguity.
259
+
260
+ Both honour decision_engine gates in .agent-settings.yml
261
+ (see docs/contracts/decision-engine-gates.md for schema).
262
+ ```
263
+
264
+ Skip block in cloud surfaces (cloud agent's invocation surface is
265
+ already chat window).
266
+
267
+ ### 12. Maintainer-only feature pointer
240
268
 
241
269
  Print one-screen hint after summary — no question, no prompt, just pointer
242
270
  for maintainers who want to opt into artefact-engagement telemetry layer.
@@ -3,6 +3,7 @@ name: optimize
3
3
  tier: 1
4
4
  description: Optimize orchestrator — routes to skills, agents-dir, augmentignore, rtk-filters
5
5
  cluster: optimize
6
+ type: orchestrator
6
7
  disable-model-invocation: true
7
8
  suggestion:
8
9
  eligible: true
@@ -3,6 +3,7 @@ name: override
3
3
  tier: 2
4
4
  description: Override orchestrator — routes to create, manage
5
5
  cluster: override
6
+ type: orchestrator
6
7
  disable-model-invocation: true
7
8
  suggestion:
8
9
  eligible: true
@@ -3,6 +3,7 @@ name: roadmap
3
3
  tier: 1
4
4
  description: Roadmap orchestrator — routes to create (authoring) and process-step / process-phase / process-full (autonomous execution).
5
5
  cluster: roadmap
6
+ type: orchestrator
6
7
  disable-model-invocation: true
7
8
  suggestion:
8
9
  eligible: true
@@ -3,6 +3,7 @@ name: tests
3
3
  tier: 2
4
4
  description: Tests orchestrator — routes to create, execute
5
5
  cluster: tests
6
+ type: orchestrator
6
7
  disable-model-invocation: true
7
8
  suggestion:
8
9
  eligible: true
@@ -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`
@@ -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
  ]