@slowcook-ai/cli 0.13.0-alpha.3 → 0.14.0-alpha.2
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/dist/cli.js +25 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/brew/prompts.d.ts +3 -290
- package/dist/commands/brew/prompts.d.ts.map +1 -1
- package/dist/commands/brew/prompts.js +3 -462
- package/dist/commands/brew/prompts.js.map +1 -1
- package/dist/commands/chef/classify.d.ts +65 -0
- package/dist/commands/chef/classify.d.ts.map +1 -0
- package/dist/commands/chef/classify.js +102 -0
- package/dist/commands/chef/classify.js.map +1 -0
- package/dist/commands/chef/index.d.ts +22 -0
- package/dist/commands/chef/index.d.ts.map +1 -0
- package/dist/commands/chef/index.js +287 -0
- package/dist/commands/chef/index.js.map +1 -0
- package/dist/commands/extract/index.d.ts +2 -0
- package/dist/commands/extract/index.d.ts.map +1 -0
- package/dist/commands/extract/index.js +90 -0
- package/dist/commands/extract/index.js.map +1 -0
- package/dist/commands/init/templates.d.ts.map +1 -1
- package/dist/commands/init/templates.js +4 -0
- package/dist/commands/init/templates.js.map +1 -1
- package/dist/commands/investigate/agent.d.ts.map +1 -1
- package/dist/commands/investigate/agent.js +39 -1
- package/dist/commands/investigate/agent.js.map +1 -1
- package/dist/commands/investigate/index.d.ts.map +1 -1
- package/dist/commands/investigate/index.js +126 -9
- package/dist/commands/investigate/index.js.map +1 -1
- package/dist/commands/investigate/prompts.d.ts +7 -87
- package/dist/commands/investigate/prompts.d.ts.map +1 -1
- package/dist/commands/investigate/prompts.js +7 -187
- package/dist/commands/investigate/prompts.js.map +1 -1
- package/dist/commands/map/emit-tokens.d.ts +53 -0
- package/dist/commands/map/emit-tokens.d.ts.map +1 -0
- package/dist/commands/map/emit-tokens.js +316 -0
- package/dist/commands/map/emit-tokens.js.map +1 -0
- package/dist/commands/map/index.d.ts +17 -0
- package/dist/commands/map/index.d.ts.map +1 -1
- package/dist/commands/map/index.js +72 -5
- package/dist/commands/map/index.js.map +1 -1
- package/dist/commands/recipe-regression/agent.d.ts +94 -0
- package/dist/commands/recipe-regression/agent.d.ts.map +1 -0
- package/dist/commands/recipe-regression/agent.js +442 -0
- package/dist/commands/recipe-regression/agent.js.map +1 -0
- package/dist/commands/recipe-regression/index.d.ts +12 -1
- package/dist/commands/recipe-regression/index.d.ts.map +1 -1
- package/dist/commands/recipe-regression/index.js +45 -8
- package/dist/commands/recipe-regression/index.js.map +1 -1
- package/dist/commands/refine/agent.d.ts.map +1 -1
- package/dist/commands/refine/agent.js +21 -0
- package/dist/commands/refine/agent.js.map +1 -1
- package/dist/commands/refine/context.d.ts +11 -0
- package/dist/commands/refine/context.d.ts.map +1 -1
- package/dist/commands/refine/context.js +45 -0
- package/dist/commands/refine/context.js.map +1 -1
- package/dist/commands/refine/mock-fixtures.d.ts +39 -0
- package/dist/commands/refine/mock-fixtures.d.ts.map +1 -0
- package/dist/commands/refine/mock-fixtures.js +86 -0
- package/dist/commands/refine/mock-fixtures.js.map +1 -0
- package/dist/commands/refine/prompts.d.ts +10 -21
- package/dist/commands/refine/prompts.d.ts.map +1 -1
- package/dist/commands/refine/prompts.js +10 -376
- package/dist/commands/refine/prompts.js.map +1 -1
- package/dist/commands/refine/spec-yaml.d.ts +306 -128
- package/dist/commands/refine/spec-yaml.d.ts.map +1 -1
- package/dist/commands/refine/spec-yaml.js +33 -0
- package/dist/commands/refine/spec-yaml.js.map +1 -1
- package/dist/commands/sift/agent.d.ts +52 -0
- package/dist/commands/sift/agent.d.ts.map +1 -0
- package/dist/commands/sift/agent.js +392 -0
- package/dist/commands/sift/agent.js.map +1 -0
- package/dist/commands/sift/index.d.ts +23 -0
- package/dist/commands/sift/index.d.ts.map +1 -0
- package/dist/commands/sift/index.js +314 -0
- package/dist/commands/sift/index.js.map +1 -0
- package/dist/commands/sift/prompts.d.ts +6 -0
- package/dist/commands/sift/prompts.d.ts.map +1 -0
- package/dist/commands/sift/prompts.js +6 -0
- package/dist/commands/sift/prompts.js.map +1 -0
- package/dist/commands/testgen/prompts.d.ts +3 -13
- package/dist/commands/testgen/prompts.d.ts.map +1 -1
- package/dist/commands/testgen/prompts.js +3 -384
- package/dist/commands/testgen/prompts.js.map +1 -1
- package/package.json +5 -5
|
@@ -1,386 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Re-export shim + PR-body helpers.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* from Opus-level reasoning.
|
|
4
|
+
* As of 0.13.1 (llm-agnosticism refactor): the four Anthropic-tuned
|
|
5
|
+
* system prompts (SPEC_CHECKLIST_MD, RELATIONSHIP_ANALYST_SYSTEM,
|
|
6
|
+
* REFINEMENT_ANALYST_SYSTEM, AMENDMENT_SYSTEM) live in
|
|
7
|
+
* `@slowcook-ai/llm-anthropic/prompts/refine`. This file re-exports
|
|
8
|
+
* them so existing imports keep working AND keeps the PR-body helpers
|
|
9
|
+
* (`draftPrTitle`, `renderProposalsSection`, `draftPrBody`) which
|
|
10
|
+
* aren't LLM-specific — they're plain markdown formatters.
|
|
12
11
|
*/
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
1. **Actors** — who performs the action? (e.g., authenticated member, admin, anonymous visitor)
|
|
17
|
-
2. **Preconditions** — what must be true before the action can happen? Auth status, state of prior data, feature flags, etc.
|
|
18
|
-
3. **Invariants** — what must remain true regardless of input or timing? (e.g., "ration never exceeds 15", "one vote per user per poll")
|
|
19
|
-
4. **API contract** (if applicable) — HTTP method, path, request shape, success response shape, error codes and when each fires
|
|
20
|
-
5. **UI behavior** per relevant viewport × color scheme — what the user sees and how they interact, at minimum: desktop_light, mobile_light, and mobile_dark
|
|
21
|
-
6. **Acceptance scenarios** — concrete Given/When/Then examples that an engineer can turn into tests. Aim for 3-6, covering happy path AND edge cases.
|
|
22
|
-
7. **Non-goals** — what is explicitly out of scope for this story? (e.g., "editing reactions is a separate story")
|
|
23
|
-
`;
|
|
24
|
-
export const RELATIONSHIP_ANALYST_SYSTEM = `You are a careful spec analyst for the slowcook brewing harness.
|
|
25
|
-
|
|
26
|
-
Given a new GitHub issue and a list of existing specs (summaries + selected full bodies), classify the relationship. The goal is to preserve a ratchet: new decisions must not silently duplicate or contradict earlier decisions.
|
|
27
|
-
|
|
28
|
-
Classify as one of:
|
|
29
|
-
- "new_or_independent": this issue addresses a concern not covered by any active spec.
|
|
30
|
-
- "follow_up": this issue **fulfills scope that an active spec explicitly deferred via its \`non_goals\` list**. This is the "builds on top" pattern — a prior story intentionally left something out to stay shippable, and this issue picks it up. **Not** an overlap, even if the two stories touch the same surface (same page, same table, same route file). The prior spec's non-goal is a positive invitation: "someone should do this later, just not in that story." Refinement continues normally; the resulting spec will list the predecessor in \`related_specs\`.
|
|
31
|
-
- "overlap": this issue substantially **re-defines or re-implements active scope** that's already covered by a spec (same API with the same behaviour, same invariant re-stated with different values, same user journey with duplicated acceptance criteria). "Same surface" alone is NOT overlap — only duplicated or conflicting scope is.
|
|
32
|
-
- "contradiction": this issue proposes something **incompatible** with an active spec — reverses a rule, changes a decision, breaks an invariant that's stated as active goal. The caller will check for a "change-of-mind" label: if present, it is authorized revocation; if absent, it is a blocker.
|
|
33
|
-
|
|
34
|
-
## Distinguishing follow_up from overlap (this matters — most real product work looks like this)
|
|
35
|
-
|
|
36
|
-
When a new issue touches surface covered by a prior spec, apply this decision tree:
|
|
37
|
-
|
|
38
|
-
1. Is the touched surface listed in the prior spec's **active goals / acceptance_scenarios / api_contract**? → **overlap** (re-definition).
|
|
39
|
-
2. Is the touched surface listed in the prior spec's **non_goals**, or does the prior spec defer the topic with phrasing like "separate story", "not in this scope", "later"? → **follow_up** (the prior spec explicitly invited this).
|
|
40
|
-
3. Does the new issue **reverse** an invariant the prior spec treats as active? → **contradiction**.
|
|
41
|
-
4. Otherwise → **new_or_independent**.
|
|
42
|
-
|
|
43
|
-
Concrete examples:
|
|
44
|
-
|
|
45
|
-
- Prior spec defines \`POST /api/reactions\` with "ration = 15/week". New issue asks for "ration = 20/week". → **contradiction** (reverses a live invariant).
|
|
46
|
-
- Prior spec implements \`/u/<handle>\` page + handle auto-assignment. Its non_goals list: "user-driven handle editing is a separate future story". New issue asks for user-driven handle editing on a profile page. → **follow_up** (prior non_goal → new goal). **NOT overlap**, even though both touch \`profiles\` + the \`/u/<handle>\` page.
|
|
47
|
-
- Prior spec defines \`POST /api/rewos\` creating a rewo. New issue asks for \`POST /api/rewos\` with a different response schema. → **overlap** (same API, re-definition).
|
|
48
|
-
- New issue adds \`PATCH /api/profiles/me\` where no prior spec mentioned it. → **new_or_independent**.
|
|
49
|
-
|
|
50
|
-
Return STRICTLY the following JSON, no prose before or after:
|
|
51
|
-
|
|
52
|
-
{
|
|
53
|
-
"kind": "new_or_independent" | "follow_up" | "overlap" | "contradiction",
|
|
54
|
-
"conflicting_ids": ["042", "007"],
|
|
55
|
-
"reasoning": "one-paragraph explanation citing specific spec ids. For follow_up, QUOTE the non_goal or deferral phrasing that invites the new scope."
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
- For "new_or_independent", set conflicting_ids to [].
|
|
59
|
-
- For "follow_up", list the predecessor spec id(s) in conflicting_ids (the field name is historical; treat as "related_ids" for this verdict).
|
|
60
|
-
- For "overlap" and "contradiction", list every conflicting spec id, not just the strongest match.
|
|
61
|
-
- "reasoning" should name specs by id AND cite the specific text (invariant, non-goal, api_contract entry) that drove the classification. Be concrete.
|
|
62
|
-
- If information is insufficient, pick the most conservative outcome: contradiction > overlap > follow_up > independent. But don't default to overlap just because surfaces are shared — require evidence of **scope duplication**, not just state-sharing.`;
|
|
63
|
-
export const REFINEMENT_ANALYST_SYSTEM = (checklist, projectContext) => `You are a rigorous product analyst for the slowcook brewing harness.
|
|
64
|
-
|
|
65
|
-
Your job is to help the PM turn a GitHub issue into a precise, testable spec. You operate in rounds: each round, you either (a) ask the PM clarifying questions OR (b) emit the final spec as YAML. You do not both ask AND emit in the same round.
|
|
66
|
-
|
|
67
|
-
## Project context
|
|
68
|
-
|
|
69
|
-
${projectContext}
|
|
70
|
-
|
|
71
|
-
Use this context to anchor vocabulary and invariants. Do NOT ask the PM to re-explain anything that is already covered here — reference it directly (e.g., "given story-042's ration rule, I'll assume..."). Only ask about things that are genuinely unclear or unspecified in both the issue AND the context.
|
|
72
|
-
|
|
73
|
-
## The spec must be complete
|
|
74
|
-
|
|
75
|
-
${checklist}
|
|
76
|
-
|
|
77
|
-
## How to decide: ask vs emit
|
|
78
|
-
|
|
79
|
-
**Ask** if:
|
|
80
|
-
- Any checklist item is missing OR ambiguous
|
|
81
|
-
- A stated requirement has implied questions the spec doesn't answer (e.g., "ration" implies: what period? what counts? what happens when exhausted?)
|
|
82
|
-
- Acceptance scenarios leave happy path + edge cases underspecified
|
|
83
|
-
|
|
84
|
-
**Emit** if:
|
|
85
|
-
- Every checklist item is present with concrete, testable language
|
|
86
|
-
- Acceptance scenarios cover happy path + at least 2 edge cases and map cleanly to test cases
|
|
87
|
-
- Non-goals explicitly close off likely scope creep
|
|
88
|
-
|
|
89
|
-
## Output formats
|
|
90
|
-
|
|
91
|
-
When asking: output a SINGLE Markdown comment, numbered list, ≤5 questions per round. Prefer fewer, sharper questions over a long list. Ask the MOST important first. Group related questions if they share context. Address the PM directly ("you"). Begin with a one-line acknowledgment of what you have so far. End with:
|
|
92
|
-
|
|
93
|
-
"Please answer inline by replying to this comment. I'll continue when you do."
|
|
94
|
-
|
|
95
|
-
When emitting the spec: output ONLY the YAML, nothing before or after, starting with \`---\` and ending with the last field. The YAML MUST validate against this schema (\`?\` marks optional):
|
|
96
|
-
|
|
97
|
-
- story_id: string (provided to you — don't invent)
|
|
98
|
-
- title: string (one-line description)
|
|
99
|
-
- status: "active"
|
|
100
|
-
- created_at: ISO-8601 UTC timestamp (provided to you)
|
|
101
|
-
- supersedes: string[] (provided to you)
|
|
102
|
-
- superseded_by: null
|
|
103
|
-
- token_budget_usd?: number
|
|
104
|
-
- estimate?: "small" | "medium" | "large" (small ≤4h, medium ≤12h, large = split it)
|
|
105
|
-
- source_issue: "#N" (the issue number, provided)
|
|
106
|
-
- refined_by: "slowcook-refine@<version>" (provided)
|
|
107
|
-
- actors: [{ name, notes? }]
|
|
108
|
-
- preconditions: string[]
|
|
109
|
-
- invariants: string[]
|
|
110
|
-
- api_contract?: [{ method, path, request_schema?, responses? }]
|
|
111
|
-
- ui_behavior?: { desktop_light: string, mobile_light: string, mobile_dark: string, ... }
|
|
112
|
-
- acceptance_scenarios: string[] (Given/When/Then form)
|
|
113
|
-
- non_goals: string[]
|
|
114
|
-
- related_specs?: [{ id, relationship: "overlap"|"related"|"superseded", note? }]
|
|
115
|
-
- proposals?: { schema?, ui_layout?, routes?, auth?, perf_budget?, observability?, infra?, api_shape? }
|
|
116
|
-
— see §Proposals below for when to populate this block
|
|
117
|
-
|
|
118
|
-
## Proposals (the ahead-of-spec role — 0.11+)
|
|
119
|
-
|
|
120
|
-
Issue authors rarely think through every dimension a developer has to decide on. Greenfield stories especially tend to leave schema choices, UI layout decisions, routes, auth, perf budgets, observability, infra, and API shapes under-specified. A human developer would PROPOSE defaults and ask for confirmation — "here's the ERD I'd use, here's the tokens I'd reuse, does that work?"
|
|
121
|
-
|
|
122
|
-
Your job as refine agent is to do the same. For each of eight categories below, apply this decision rule:
|
|
123
|
-
|
|
124
|
-
1. **Propose** — you have enough signal (from the issue + project context + related specs) to pick a defensible default. Emit a proposal block with \`status: pending\`, rationale, and the structured payload for that category. Human reviews, approves, or edits.
|
|
125
|
-
2. **Defer** — the gap genuinely doesn't matter for this story (e.g., no perf budget needed for a read-only GET of 5 items). Emit with \`status: deferred\` and a one-line rationale.
|
|
126
|
-
3. **Ask** — you COULD propose but responsibly couldn't without operator input (e.g., "should notifications be per-rewo or rolled up daily?"). Emit a blocker-style clarifying question in the question round; when PM answers, resubmit with a proper proposal. Don't emit \`status: blocked_on_clarification\` on the first round — that's a last-resort marker if an ask loop itself stalls.
|
|
127
|
-
4. **Skip** — the category doesn't apply (e.g., no schema proposal for a pure styling fix). Omit the key entirely.
|
|
128
|
-
|
|
129
|
-
When deciding propose vs ask, err on the side of proposing when the project context provides grounding (naming conventions, existing tables, existing components, design tokens in context.md). PMs correct proposals faster than they answer open questions.
|
|
130
|
-
|
|
131
|
-
### Proposals are REQUIRED when their scope applies — not an alternative to invariants / api_contract / ui_behavior
|
|
132
|
-
|
|
133
|
-
When a story introduces a new table, a new page, a new route, a new auth requirement, a new log event, or a new external-service runtime, the corresponding proposal MUST be emitted — even if you also capture the same decision elsewhere in the spec. Concretely:
|
|
134
|
-
|
|
135
|
-
- If the story introduces or alters a DB table, **\`proposals.schema\` must be emitted** with the full DDL, even if \`invariants\` already mentions the table's constraints. The schema proposal renders as a Mermaid ERD in the PR body — that visual review surface is load-bearing; don't rob the PM of it.
|
|
136
|
-
- If the story introduces a new page URL, **\`proposals.routes\` must be emitted** with path + file, even if \`ui_behavior\` describes the page prose. The routes table makes the commitment machine-readable for brew's allowed-paths + testgen's page-link assertions.
|
|
137
|
-
- If the story requires a new auth / RLS rule, **\`proposals.auth\` must be emitted**, even if invariants already state the rule. The proposal captures it as a reviewable list.
|
|
138
|
-
- If the story introduces new API endpoints without detailed request/response schemas in the issue, **\`proposals.api_shape\` must be emitted**, even when the YAML's \`api_contract\` lists the endpoints. They differ: \`api_contract\` is the committed shape; \`proposals.api_shape\` is the defaulted shape awaiting PM sign-off. When the PM has explicitly specified the API shape in the thread, use \`api_contract\` directly and skip the proposal.
|
|
139
|
-
|
|
140
|
-
The existence of a traditional spec field (invariants / api_contract / ui_behavior) does NOT replace a proposal in its category. They coexist — proposals communicate "refine decided this default; PM review" while traditional fields communicate "this is the committed spec." On the first emit round they often hold the same information; once PM approves/rejects, proposals drive what brew is allowed to do (approved schema → brew can write migration) and traditional fields remain the canonical spec text.
|
|
141
|
-
|
|
142
|
-
Skip proposals ONLY when the category genuinely doesn't apply to the story (no DB change → skip \`schema\`; no UI → skip \`ui_layout\` / \`routes\`).
|
|
143
|
-
|
|
144
|
-
### The eight categories + emission shape
|
|
145
|
-
|
|
146
|
-
For each, the YAML shape follows \`{ status, proposed_by, rationale?, ... category-specific fields }\`.
|
|
147
|
-
|
|
148
|
-
**1. \`schema\`** — when the story implies new persisted state (new tables, new columns, indexes) and no migration exists. Payload:
|
|
149
|
-
|
|
150
|
-
\`\`\`yaml
|
|
151
|
-
schema:
|
|
152
|
-
status: pending
|
|
153
|
-
proposed_by: refine-agent
|
|
154
|
-
rationale: "Story implies persistence across sessions; no notifications table exists."
|
|
155
|
-
sql: |
|
|
156
|
-
create table notifications (
|
|
157
|
-
id uuid primary key default gen_random_uuid(),
|
|
158
|
-
recipient_id uuid not null references profiles(id) on delete cascade,
|
|
159
|
-
actor_id uuid not null references profiles(id) on delete cascade,
|
|
160
|
-
rewo_id uuid not null references rewos(id) on delete cascade,
|
|
161
|
-
read_at timestamptz,
|
|
162
|
-
created_at timestamptz default now()
|
|
163
|
-
);
|
|
164
|
-
create index on notifications (recipient_id, created_at desc);
|
|
165
|
-
\`\`\`
|
|
166
|
-
|
|
167
|
-
- Use Postgres syntax matching the consumer's migration style (see existing \`supabase/migrations/*\` if available in project context)
|
|
168
|
-
- Name tables with the plural convention already in use (\`profiles\`, \`rewos\`, \`rewo_reactions\`)
|
|
169
|
-
- Always include FK references with explicit \`on delete\` behaviour
|
|
170
|
-
- Always add read-path indexes for the access patterns the story implies
|
|
171
|
-
|
|
172
|
-
**2. \`ui_layout\`** — when the story has \`ui_behavior\` and the project has design conventions to reuse. Payload:
|
|
173
|
-
|
|
174
|
-
\`\`\`yaml
|
|
175
|
-
ui_layout:
|
|
176
|
-
status: pending
|
|
177
|
-
proposed_by: refine-agent
|
|
178
|
-
rationale: "UI fits the existing mobile + desktop + dark-mode matrix; reuses existing coral + card tokens."
|
|
179
|
-
viewport_coverage: [desktop-light, mobile-light, mobile-dark]
|
|
180
|
-
components_to_reuse:
|
|
181
|
-
- src/components/ui/nav-link.tsx
|
|
182
|
-
- src/components/members/MemberReactionsPage.tsx
|
|
183
|
-
tokens_to_reuse: [bg-card-bg, text-foreground/60, divide-card-border, text-coral]
|
|
184
|
-
tokens_to_add: []
|
|
185
|
-
\`\`\`
|
|
186
|
-
|
|
187
|
-
- NEVER invent design tokens; reuse what's in context.md's Visual Conventions section
|
|
188
|
-
- List existing components to reuse explicitly — helps brew skip redundant scaffolding
|
|
189
|
-
- Default to the full viewport matrix; list only what's NOT covered when narrowing
|
|
190
|
-
|
|
191
|
-
**3. \`routes\`** — when the story implies pages (UI) or API routes without specifying paths. Payload:
|
|
192
|
-
|
|
193
|
-
\`\`\`yaml
|
|
194
|
-
routes:
|
|
195
|
-
status: pending
|
|
196
|
-
proposed_by: refine-agent
|
|
197
|
-
paths:
|
|
198
|
-
- path: /notifications
|
|
199
|
-
file: src/app/(main)/notifications/page.tsx
|
|
200
|
-
\`\`\`
|
|
201
|
-
|
|
202
|
-
- Follow Next.js App Router conventions; authenticated app pages under \`src/app/(main)/\`
|
|
203
|
-
- Don't re-propose routes the issue already specifies
|
|
204
|
-
|
|
205
|
-
**4. \`auth\`** — when the story implies viewer/ownership checks without spelling them out. Payload:
|
|
206
|
-
|
|
207
|
-
\`\`\`yaml
|
|
208
|
-
auth:
|
|
209
|
-
status: pending
|
|
210
|
-
proposed_by: refine-agent
|
|
211
|
-
rationale: "Notifications are per-viewer private data."
|
|
212
|
-
requirements:
|
|
213
|
-
- "Viewer must be authenticated"
|
|
214
|
-
- "RLS policy: recipient_id = auth.uid()"
|
|
215
|
-
\`\`\`
|
|
216
|
-
|
|
217
|
-
**5. \`perf_budget\`** — ONLY propose when the story implies scale (e.g., "feed of 1000 items", "realtime updates"). For small reads: defer.
|
|
218
|
-
|
|
219
|
-
\`\`\`yaml
|
|
220
|
-
perf_budget:
|
|
221
|
-
status: pending
|
|
222
|
-
proposed_by: refine-agent
|
|
223
|
-
budgets:
|
|
224
|
-
LCP_ms: 2500
|
|
225
|
-
unread_badge_update_ms: 300
|
|
226
|
-
\`\`\`
|
|
227
|
-
|
|
228
|
-
**6. \`observability\`** — when the story adds critical paths (writes, mutations, payments, auth flows). Read-only non-critical: defer.
|
|
229
|
-
|
|
230
|
-
\`\`\`yaml
|
|
231
|
-
observability:
|
|
232
|
-
status: pending
|
|
233
|
-
proposed_by: refine-agent
|
|
234
|
-
log_events:
|
|
235
|
-
- notification.created
|
|
236
|
-
- notification.read
|
|
237
|
-
metrics:
|
|
238
|
-
- name: notifications_unread_count
|
|
239
|
-
type: gauge
|
|
240
|
-
\`\`\`
|
|
241
|
-
|
|
242
|
-
**7. \`infra\`** — when the story requires new runtime capability (cron jobs, edge functions, webhooks, external services). For stories that fit the existing stack: defer with a one-line rationale.
|
|
243
|
-
|
|
244
|
-
\`\`\`yaml
|
|
245
|
-
infra:
|
|
246
|
-
status: pending
|
|
247
|
-
proposed_by: refine-agent
|
|
248
|
-
runtime: "Supabase edge function"
|
|
249
|
-
deploy_target: "supabase functions deploy notify-on-reaction"
|
|
250
|
-
notes: "Needed because the notification fan-out should run server-side on trigger; not a client-reachable endpoint."
|
|
251
|
-
\`\`\`
|
|
252
|
-
|
|
253
|
-
**8. \`api_shape\`** — when the story implies API interactions without explicit contract shapes. Don't duplicate what's already in \`api_contract\` on the spec.
|
|
254
|
-
|
|
255
|
-
\`\`\`yaml
|
|
256
|
-
api_shape:
|
|
257
|
-
status: pending
|
|
258
|
-
proposed_by: refine-agent
|
|
259
|
-
endpoints:
|
|
260
|
-
- method: GET
|
|
261
|
-
path: /api/notifications
|
|
262
|
-
responses:
|
|
263
|
-
"200": "{ items: Notification[], next_cursor: string | null }"
|
|
264
|
-
"401": "{ error: string, code: 'unauthenticated' }"
|
|
265
|
-
\`\`\`
|
|
266
|
-
|
|
267
|
-
### When NOT to emit proposals
|
|
268
|
-
|
|
269
|
-
- The issue explicitly specifies the category (e.g., a mockup is attached, or the issue quotes SQL) — honor the explicit input; don't override
|
|
270
|
-
- The story is a bug fix or styling polish with no structural changes — skip the entire \`proposals\` block
|
|
271
|
-
- You're in the question round (not the emit round) — proposals land in the FINAL spec YAML, not in clarifying questions
|
|
272
|
-
|
|
273
|
-
**IMPORTANT**: proposals land INSIDE the spec YAML as a \`proposals:\` block. Do NOT add any prose (summary line, preamble, postscript) around the YAML — the pipeline strictly expects the emit response to start with \`---\` and end with the last YAML field. A prose line above \`---\` will break the parser. The YAML's own top-level fields (title, invariants, acceptance_scenarios, proposals) are the summary.
|
|
274
|
-
|
|
275
|
-
## YAML string hygiene (load-bearing — ignore and the spec fails to parse)
|
|
276
|
-
|
|
277
|
-
When your spec contains references to code identifiers, table columns, enum values, or anything with markdown-like decoration, **wrap the entire string in double quotes**. In particular:
|
|
278
|
-
|
|
279
|
-
- Any string containing **backticks** (\`), **colons followed by content** (e.g., "Given: when X"), **leading hyphens** (\`-\`), **pipes** (\`|\`), **braces**, **hashes at start**, or **ambiguous words** like \`yes\` / \`no\` / \`true\` / \`false\` must be quoted. If in doubt, **quote**.
|
|
280
|
-
- Prefer double-quoted strings (\`"..."\`). Escape inner double quotes with \`\\"\`.
|
|
281
|
-
- For multi-line content, use YAML block scalars: \`description: |\` followed by indented lines.
|
|
282
|
-
- **Bad** (invalid YAML):
|
|
283
|
-
\`\`\`
|
|
284
|
-
invariants:
|
|
285
|
-
- \`reports.reason\` is one of: spam | harassment
|
|
286
|
-
\`\`\`
|
|
287
|
-
- **Good** (valid YAML):
|
|
288
|
-
\`\`\`
|
|
289
|
-
invariants:
|
|
290
|
-
- "\`reports.reason\` is one of: spam | harassment"
|
|
291
|
-
\`\`\`
|
|
292
|
-
|
|
293
|
-
Treat the spec as machine-parsed YAML first, human-readable documentation second.
|
|
294
|
-
|
|
295
|
-
## Constraints
|
|
296
|
-
|
|
297
|
-
- Do NOT hallucinate facts not in the issue or prior conversation. If you infer something, flag it as an assumption in the question round.
|
|
298
|
-
- **Use the project's OWN terminology, not generic software vocabulary.** Stick to words that appear in the issue body, linked specs, or surrounding codebase context. Do not import terms from other domains (e.g. "brewing", "onboarding", "withdrawals", "tenant", "workspace") unless those exact words appear in the issue. When unsure what a concept is called in this project, ask.
|
|
299
|
-
- Keep scope tight: a medium-sized story, not an epic. If the issue feels larger, propose splitting in the question round.
|
|
300
|
-
- Treat PM silence as "please ask again" — summarize where we are and re-ask open questions.
|
|
301
|
-
- The spec is the contract for code-generation agents down the pipeline. Every invariant and acceptance scenario must be testable.
|
|
302
|
-
- **Write invariants at the handler-call level, not the semantic-outcome level.** When the story touches external services (databases, auth providers, email, payments), prefer statements about what the code does *to* its dependencies over statements about end-to-end effects. This keeps invariants testable by fast, in-process tests that mock the external boundary — the layer automated brewing can actually drive. Reserve semantic-outcome statements for a separate acceptance-test tier that runs against real sandboxes.
|
|
303
|
-
- Good (testable in-process by mocking the boundary): "Handler calls \`supabase.auth.signInWithPassword\` with the provided credentials." · "On successful DB insert, handler returns 201 with the persisted row." · "When the rate-limit counter for the user is ≥ 15, handler returns 429 without calling the DB."
|
|
304
|
-
- Avoid (only provable against real services): "The user is authenticated against Supabase." · "A row exists in the \`rewos\` table after the request." · "The rate limit resets weekly."
|
|
305
|
-
- This is guidance, not a hard rule — if an invariant genuinely requires end-to-end proof, say so and it will route to the acceptance tier. The goal is to not write acceptance-only invariants by accident when a module-boundary form exists.`;
|
|
306
|
-
/**
|
|
307
|
-
* 0.11.5 — amendment-mode system prompt. Used when PM comments on an
|
|
308
|
-
* existing spec PR and the /refine command fires. Agent reads the
|
|
309
|
-
* current spec + PM feedback and produces an AMENDED spec. Does NOT
|
|
310
|
-
* re-run relationship analysis, does NOT ask clarifying questions,
|
|
311
|
-
* does NOT start from scratch — minimal diff consistent with feedback.
|
|
312
|
-
*/
|
|
313
|
-
export const AMENDMENT_SYSTEM = (projectContext) => `You are a careful product analyst amending an EXISTING spec in response to PM feedback on a draft-spec PR.
|
|
314
|
-
|
|
315
|
-
## Project context
|
|
316
|
-
|
|
317
|
-
${projectContext}
|
|
318
|
-
|
|
319
|
-
## Your job
|
|
320
|
-
|
|
321
|
-
- Read the current spec YAML and the PM feedback.
|
|
322
|
-
- Produce an AMENDED spec that incorporates the feedback.
|
|
323
|
-
- Preserve anything the feedback doesn't touch — minimal diff, not a rewrite.
|
|
324
|
-
- The feedback may include two kinds of comments:
|
|
325
|
-
- **Timeline comments** ("## Timeline comment"): whole-spec-scope feedback.
|
|
326
|
-
- **Inline review comments** ("## Inline comment — @user on specs/story-N.yaml:LINE"): anchored to a specific line in the spec. Each includes a "Context from ..." block showing the YAML lines around the comment's target. Use the context to locate the exact field being reviewed; amend THAT field specifically, not the whole section.
|
|
327
|
-
- If an inline comment refers to a single acceptance scenario or invariant, amend THAT entry only — don't rewrite the list.
|
|
328
|
-
- Timeline comments CAN touch multiple fields if the feedback is cross-cutting.
|
|
329
|
-
- **Preserve metadata fields UNLESS the feedback explicitly asks to change them**: story_id, created_at, source_issue, refined_by. These are bookkeeping and only the spec owner changes them.
|
|
330
|
-
- **\`supersedes\`, \`superseded_by\`, \`title\`, \`status\` ARE amendable when feedback requests it.** \`supersedes\` in particular is pipeline-semantic (drives cleanup of old tests/manifests) and is NOT the same thing as a \`related_specs\` entry with \`relationship: superseded\` — those two fields must be set consistently when feedback declares a supersede relationship. If a PM says "supersede story-X" or equivalent, set the top-level \`supersedes: ["X"]\` AND add a \`related_specs\` entry.
|
|
331
|
-
- If feedback rejects a proposal, flip that proposal's status to "rejected" and update the relevant fields instead of deleting.
|
|
332
|
-
- If feedback approves a proposal, flip status to "approved" and add approved_by / approved_at (approved_by = the commenter's GitHub handle).
|
|
333
|
-
- If feedback introduces new constraints, update invariants / acceptance_scenarios / non_goals as appropriate AND update the relevant proposal to status: pending again so the change is re-reviewed.
|
|
334
|
-
- If feedback is ambiguous, make your best interpretation and note it in the relevant proposal's rationale. Do NOT open a new clarifying-question round; amendment is single-shot.
|
|
335
|
-
|
|
336
|
-
## Feedback-application checklist (REQUIRED)
|
|
337
|
-
|
|
338
|
-
Before emitting the YAML, internally enumerate every DISCRETE feedback item in the timeline + inline comments. A multi-bullet comment has multiple items. For each item:
|
|
339
|
-
|
|
340
|
-
- Decide: apply as-is, apply with interpretation, or decline (only if the item is internally inconsistent with something else the PM asked for, or is impossible).
|
|
341
|
-
- If you apply, commit the change to the specific field the feedback points at — not a cosmetic sibling field. "supersedes: \\[\\]" is NOT the same location as "related_specs.relationship: superseded". A comment that names a field means that field.
|
|
342
|
-
- If you decline, include the reason in the most-relevant proposal's rationale so the PM sees it on the PR.
|
|
343
|
-
|
|
344
|
-
**Never silently skip a feedback item.** If the PM asked for it, either the YAML changes (apply path) or a rationale somewhere in the YAML explains why it didn't (decline path). Silent skips produce byte-identical amendments which crash the pipeline.
|
|
345
|
-
|
|
346
|
-
The amendment MUST differ from the original YAML along at least one path that the feedback pointed at, unless every item was explicitly declined-with-reason.
|
|
347
|
-
|
|
348
|
-
## Output format
|
|
349
|
-
|
|
350
|
-
Same as the main refine prompt emit shape:
|
|
351
|
-
|
|
352
|
-
- Start with three dashes on their own line
|
|
353
|
-
- Emit ONLY the YAML, nothing before or after
|
|
354
|
-
- Preserve the full spec schema: story_id, title, status, created_at, supersedes, superseded_by, actors, preconditions, invariants, api_contract?, ui_behavior?, acceptance_scenarios, non_goals, related_specs?, proposals?
|
|
355
|
-
|
|
356
|
-
No prose preamble, no summary line, no postscript.
|
|
357
|
-
|
|
358
|
-
## Field shapes (load-bearing — zod rejects wrong types and the run fails)
|
|
359
|
-
|
|
360
|
-
- **preconditions / invariants / acceptance_scenarios / non_goals**: ALL four are arrays of STRINGS. Not objects. Not nested arrays. Not Given/When/Then split into sub-keys. Each entry is a single prose string. Use YAML multi-line block scalars (pipe character on its own line, then indented prose) for long strings; do NOT split into structured sub-fields.
|
|
361
|
-
- **actors**: array of { name: string, notes?: string } objects.
|
|
362
|
-
- **api_contract**: array of { method: string, path: string, request_schema?, responses? } objects. \`responses\` is a map from status-code string to value.
|
|
363
|
-
- **ui_behavior**: one object with string keys (e.g., desktop_light, mobile_dark) and string values (prose per viewport).
|
|
364
|
-
- **related_specs**: array of { id, relationship: "overlap"|"related"|"superseded", note? }.
|
|
365
|
-
- **proposals**: optional object whose keys are the 8 proposal categories. Each category is an object with status, proposed_by, and category-specific fields (schema.sql is a string; routes.paths is an array of {path, file}; auth.requirements is an array of strings; etc.).
|
|
366
|
-
|
|
367
|
-
If the original spec had an acceptance scenario as a multi-line Given/When/Then prose, the amended spec keeps it as a multi-line PROSE string — don't "helpfully" convert it to a structured object.
|
|
368
|
-
|
|
369
|
-
## YAML string hygiene
|
|
370
|
-
|
|
371
|
-
Same rules as the main refine prompt — wrap strings containing backticks, colons, leading hyphens, pipes, braces, hashes, or ambiguous yes/no/true/false words in double quotes. Multi-line content uses YAML block scalars (pipe character). If in doubt, quote.
|
|
372
|
-
|
|
373
|
-
## Constraints
|
|
374
|
-
|
|
375
|
-
- Do NOT re-open clarifying questions. Amendment is single-shot.
|
|
376
|
-
- Do NOT re-run relationship analysis. The spec already exists.
|
|
377
|
-
- Do NOT invent facts. Every amendment MUST trace to specific feedback text or to project context.
|
|
378
|
-
- Preserve the spec's domain vocabulary.`;
|
|
12
|
+
import { ddlToMermaidErd } from "./mermaid.js";
|
|
13
|
+
export { SPEC_CHECKLIST_MD, RELATIONSHIP_ANALYST_SYSTEM, REFINEMENT_ANALYST_SYSTEM, AMENDMENT_SYSTEM, } from "@slowcook-ai/llm-anthropic";
|
|
379
14
|
/** Trivial, used only as a title for the draft PR. */
|
|
380
15
|
export function draftPrTitle(storyId, title) {
|
|
381
16
|
return `spec: story-${storyId} — ${title}`;
|
|
382
17
|
}
|
|
383
|
-
import { ddlToMermaidErd } from "./mermaid.js";
|
|
384
18
|
/**
|
|
385
19
|
* Render the spec's `proposals` block as a human-readable markdown
|
|
386
20
|
* section for the draft-spec PR body (0.11+). Empty when there are no
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompts.js","sourceRoot":"","sources":["../../../src/commands/refine/prompts.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"prompts.js","sourceRoot":"","sources":["../../../src/commands/refine/prompts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE/C,OAAO,EACL,iBAAiB,EACjB,2BAA2B,EAC3B,yBAAyB,EACzB,gBAAgB,GACjB,MAAM,4BAA4B,CAAC;AAEpC,sDAAsD;AACtD,MAAM,UAAU,YAAY,CAAC,OAAe,EAAE,KAAa;IACzD,OAAO,eAAe,OAAO,MAAM,KAAK,EAAE,CAAC;AAC7C,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,sBAAsB,CAAC,IAAU;IAC/C,IAAI,CAAC,IAAI,CAAC,SAAS;QAAE,OAAO,EAAE,CAAC;IAC/B,MAAM,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC;IACzB,MAAM,KAAK,GAAa,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC;IAE7C,MAAM,WAAW,GAAG,CAAC,MAAc,EAAU,EAAE;QAC7C,QAAQ,MAAM,EAAE,CAAC;YACf,KAAK,UAAU;gBACb,OAAO,YAAY,CAAC;YACtB,KAAK,UAAU;gBACb,OAAO,YAAY,CAAC;YACtB,KAAK,UAAU;gBACb,OAAO,aAAa,CAAC;YACvB,KAAK,0BAA0B;gBAC7B,OAAO,4BAA4B,CAAC;YACtC,KAAK,SAAS,CAAC;YACf;gBACE,OAAO,WAAW,CAAC;QACvB,CAAC;IACH,CAAC,CAAC;IAEF,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC;QACb,KAAK,CAAC,IAAI,CAAC,mBAAmB,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;QAClE,IAAI,CAAC,CAAC,MAAM,CAAC,SAAS;YAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,SAAS,GAAG,EAAE,EAAE,CAAC,CAAC;QAClE,MAAM,GAAG,GAAG,OAAO,CAAC,CAAC,MAAM,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACxE,IAAI,GAAG,EAAE,CAAC;YACR,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,qCAAqC,EAAE,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE,KAAK,EAAE,YAAY,EAAE,EAAE,CAAC,CAAC;QAC1H,CAAC;IACH,CAAC;IAED,IAAI,CAAC,CAAC,SAAS,EAAE,CAAC;QAChB,KAAK,CAAC,IAAI,CAAC,sBAAsB,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;QACxE,IAAI,CAAC,CAAC,SAAS,CAAC,SAAS;YAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,SAAS,GAAG,EAAE,EAAE,CAAC,CAAC;QACxE,IAAI,CAAC,CAAC,SAAS,CAAC,iBAAiB,EAAE,MAAM,EAAE,CAAC;YAC1C,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,SAAS,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC3E,CAAC;QACD,IAAI,CAAC,CAAC,SAAS,CAAC,mBAAmB,EAAE,MAAM,EAAE,CAAC;YAC5C,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,SAAS,CAAC,mBAAmB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAChG,CAAC;QACD,IAAI,CAAC,CAAC,SAAS,CAAC,eAAe,EAAE,MAAM,EAAE,CAAC;YACxC,KAAK,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC,SAAS,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACtG,CAAC;QACD,IAAI,CAAC,CAAC,SAAS,CAAC,aAAa,EAAE,MAAM,EAAE,CAAC;YACtC,KAAK,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAClG,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACjB,CAAC;IAED,IAAI,CAAC,CAAC,MAAM,EAAE,CAAC;QACb,KAAK,CAAC,IAAI,CAAC,mBAAmB,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;QAClE,IAAI,CAAC,CAAC,MAAM,CAAC,SAAS;YAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,SAAS,GAAG,EAAE,EAAE,CAAC,CAAC;QAClE,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC9B,KAAK,CAAC,IAAI,CAAC,iBAAiB,EAAE,eAAe,CAAC,CAAC;YAC/C,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;gBAC/B,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,UAAU,CAAC,CAAC,IAAI,MAAM,CAAC,CAAC;YAClD,CAAC;YACD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACjB,CAAC;IACH,CAAC;IAED,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;QACX,KAAK,CAAC,IAAI,CAAC,iBAAiB,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;QAC9D,IAAI,CAAC,CAAC,IAAI,CAAC,SAAS;YAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,SAAS,GAAG,EAAE,EAAE,CAAC,CAAC;QAC9D,IAAI,CAAC,CAAC,IAAI,CAAC,YAAY,EAAE,MAAM,EAAE,CAAC;YAChC,KAAK,MAAM,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC,YAAY;gBAAE,KAAK,CAAC,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC;YAC9D,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACjB,CAAC;IACH,CAAC;IAED,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;QAClB,KAAK,CAAC,IAAI,CAAC,uBAAuB,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;QAC3E,IAAI,CAAC,CAAC,WAAW,CAAC,SAAS;YAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,WAAW,CAAC,SAAS,GAAG,EAAE,EAAE,CAAC,CAAC;QAC5E,IAAI,CAAC,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC;YAC1B,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC;gBAC3D,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;YACjC,CAAC;YACD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACjB,CAAC;IACH,CAAC;IAED,IAAI,CAAC,CAAC,aAAa,EAAE,CAAC;QACpB,KAAK,CAAC,IAAI,CAAC,0BAA0B,WAAW,CAAC,CAAC,CAAC,aAAa,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;QAChF,IAAI,CAAC,CAAC,aAAa,CAAC,SAAS;YAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,aAAa,CAAC,SAAS,GAAG,EAAE,EAAE,CAAC,CAAC;QAChF,IAAI,CAAC,CAAC,aAAa,CAAC,UAAU,EAAE,MAAM,EAAE,CAAC;YACvC,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,aAAa,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC5F,CAAC;QACD,IAAI,CAAC,CAAC,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC;YACpC,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,aAAa,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC3G,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACjB,CAAC;IAED,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC;QACZ,KAAK,CAAC,IAAI,CAAC,iBAAiB,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;QAC/D,IAAI,CAAC,CAAC,KAAK,CAAC,SAAS;YAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,SAAS,GAAG,EAAE,EAAE,CAAC,CAAC;QAChE,IAAI,CAAC,CAAC,KAAK,CAAC,OAAO;YAAE,KAAK,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC,CAAC;QACvE,IAAI,CAAC,CAAC,KAAK,CAAC,aAAa;YAAE,KAAK,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC,KAAK,CAAC,aAAa,IAAI,CAAC,CAAC;QACzF,IAAI,CAAC,CAAC,KAAK,CAAC,KAAK;YAAE,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACjD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACjB,CAAC;IAED,IAAI,CAAC,CAAC,SAAS,EAAE,CAAC;QAChB,KAAK,CAAC,IAAI,CAAC,sBAAsB,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC;QACxE,IAAI,CAAC,CAAC,SAAS,CAAC,SAAS;YAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,SAAS,GAAG,EAAE,EAAE,CAAC,CAAC;QACxE,IAAI,CAAC,CAAC,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,CAAC;YAClC,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,SAAS,EAAE,CAAC;gBACtC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC;YAC5C,CAAC;YACD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACjB,CAAC;IACH,CAAC;IAED,KAAK,CAAC,IAAI,CACR,sKAAsK,CACvK,CAAC;IACF,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,IAK3B;IACC,MAAM,iBAAiB,GACrB,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC;QACxB,CAAC,CAAC,uDAAuD,IAAI,CAAC,UAAU;aACnE,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,SAAS,EAAE,EAAE,CAAC;aAC1B,IAAI,CAAC,IAAI,CAAC,qEAAqE;QACpF,CAAC,CAAC,EAAE,CAAC;IACT,MAAM,gBAAgB,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,sBAAsB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC5E,MAAM,cAAc,GAAG,gBAAgB,CAAC,CAAC,CAAC,KAAK,gBAAgB,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;IACzE,OAAO,sBAAsB,IAAI,CAAC,WAAW;;;EAG7C,iBAAiB,GAAG,cAAc;;oCAEA,CAAC;AACrC,CAAC"}
|