@zizzfizzix/aef 0.1.0 → 0.2.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/core/ai/framework-feedback/README.md +4 -0
- package/dist/{chunk-YENPV3OD.js → chunk-QEUDIAAQ.js} +12 -4
- package/dist/chunk-QEUDIAAQ.js.map +1 -0
- package/dist/cli/index.js +170 -41
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +13 -9
- package/dist/index.js +3 -1
- package/package.json +1 -1
- package/schemas/framework.config.schema.json +7 -0
- package/dist/chunk-YENPV3OD.js.map +0 -1
|
@@ -5,6 +5,10 @@ Capture is on by default and writes only files here — **zero egress**, always
|
|
|
5
5
|
`git diff`. The `improve-framework` skill (feedback-drain mode) batches these into a framework PR;
|
|
6
6
|
`project`-scoped lessons never land here (they go to `.ai/lessons.md`).
|
|
7
7
|
|
|
8
|
+
> **Note:** `improve-framework` is in the `framework` tier (opt-in). Install it by adding
|
|
9
|
+
> `"tiers": ["framework"]` to `framework.config.json` and re-running `aef init`, or by running
|
|
10
|
+
> `aef add framework`.
|
|
11
|
+
|
|
8
12
|
## Scope tag
|
|
9
13
|
|
|
10
14
|
Each entry declares a `scope`:
|
|
@@ -107,6 +107,7 @@ var FrameworkConfigSchema = z.object({
|
|
|
107
107
|
defaultBranch: z.string().optional(),
|
|
108
108
|
labels: z.array(z.string()).optional()
|
|
109
109
|
}).strict().optional(),
|
|
110
|
+
tiers: z.array(z.string()).describe('Opt-in tiers to install in addition to the defaults (e.g. ["framework", "automation"]).').optional(),
|
|
110
111
|
source: z.object({
|
|
111
112
|
path: z.string().nullable().describe("Local checkout path; if null, clone repo on demand.").optional(),
|
|
112
113
|
repo: z.string().nullable().optional()
|
|
@@ -142,14 +143,20 @@ var TiersSchema = z.object({
|
|
|
142
143
|
// src/core/select.ts
|
|
143
144
|
import { readFileSync as readFileSync2 } from "fs";
|
|
144
145
|
import { join as join2 } from "path";
|
|
146
|
+
function loadTiers(root) {
|
|
147
|
+
return TiersSchema.parse(JSON.parse(readFileSync2(join2(root, "core/ai/skills/tiers.json"), "utf8")));
|
|
148
|
+
}
|
|
145
149
|
function selectSkills(root, config) {
|
|
146
|
-
const tiers =
|
|
150
|
+
const tiers = loadTiers(root);
|
|
147
151
|
const requires = tiers.requires ?? {};
|
|
152
|
+
const skipped = [];
|
|
153
|
+
for (const t of config.tiers ?? [])
|
|
154
|
+
if (!(t in tiers.tiers)) skipped.push(`tier '${t}' (unknown \u2014 not in tiers.json)`);
|
|
155
|
+
const activeTiers = [...tiers.default, ...config.tiers ?? []];
|
|
148
156
|
const candidates = [];
|
|
149
|
-
for (const t of
|
|
157
|
+
for (const t of activeTiers)
|
|
150
158
|
for (const s of tiers.tiers[t]?.skills ?? []) if (!candidates.includes(s)) candidates.push(s);
|
|
151
159
|
const skills = [];
|
|
152
|
-
const skipped = [];
|
|
153
160
|
for (const s of candidates) {
|
|
154
161
|
const axis = requires[s];
|
|
155
162
|
if (axis && !config[axis]) skipped.push(`${s} (needs ${axis})`);
|
|
@@ -201,7 +208,8 @@ export {
|
|
|
201
208
|
FrameworkConfigSchema,
|
|
202
209
|
AdapterSchema,
|
|
203
210
|
TiersSchema,
|
|
211
|
+
loadTiers,
|
|
204
212
|
selectSkills,
|
|
205
213
|
mergeFile
|
|
206
214
|
};
|
|
207
|
-
//# sourceMappingURL=chunk-
|
|
215
|
+
//# sourceMappingURL=chunk-QEUDIAAQ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/render.ts","../src/core/contracts.ts","../src/core/select.ts","../src/core/merge.ts"],"sourcesContent":["// Pure skill renderer — the heart of the framework. No I/O beyond reading source\n// files; returns { rendered, manifest, digest }. Kept dependency-light (node builtins\n// + a type-only contract import) because it runs in consumer repos, in CI, and inside\n// the improve-framework skill.\n//\n// Properties (proven in docs/render-model.md and asserted by the gate): convergence,\n// determinism, provenance, per-skill digest scoping.\nimport { readFileSync, existsSync } from 'node:fs'\nimport { join, relative } from 'node:path'\nimport { createHash } from 'node:crypto'\nimport type { FrameworkConfig } from './contracts.js'\n\nconst AXES = ['orm', 'ui', 'stack'] as const\ntype Axis = (typeof AXES)[number]\n\nconst sha = (s: string): string => createHash('sha256').update(s).digest('hex').slice(0, 12)\nconst norm = (s: string): string => s.replace(/\\r\\n/g, '\\n')\n\nconst OPEN = /^<!--\\s*SLOT:([\\w.-]+)\\s*-->$/\nconst CLOSE = /^<!--\\s*\\/SLOT:([\\w.-]+)\\s*-->$/\n\n// Shared, single source of truth for what a slot marker is — imported by the gate so\n// the gate and the renderer can never disagree (a slot is a marker ALONE ON ITS OWN\n// LINE; `SLOT:` mentioned in prose/backticks is not a slot and is never touched).\nexport const SLOT_OPEN = OPEN\nexport const SLOT_ANY = /^<!--\\s*\\/?SLOT:[\\w.-]+\\s*-->$/\n\nexport interface InputRef {\n path: string\n sha: string\n}\n\nexport interface Region {\n source: string\n adapter: string | null\n slot: string | null\n startLine: number\n endLine: number\n}\n\nexport interface RenderManifest {\n skill: string\n selection: Partial<Record<Axis, string>>\n digest: string\n note: string\n inputs: InputRef[]\n regions: Region[]\n}\n\nexport interface RenderResult {\n rendered: string\n manifest: RenderManifest\n digest: string\n}\n\ninterface SlotProvider {\n adapter: string\n axis: Axis\n source: string\n content: string\n}\n\nexport function renderSkill(root: string, config: FrameworkConfig, skill: string): RenderResult {\n const rel = (p: string): string => relative(root, p)\n\n // Active adapter per axis -> slot lookup (no inputs counted here).\n const selected: Partial<Record<Axis, string>> = {}\n for (const axis of AXES) {\n const value = config[axis]\n if (value) selected[axis] = value\n }\n\n const slotProviders: Record<string, SlotProvider> = {}\n for (const [axis, adapter] of Object.entries(selected) as [Axis, string][]) {\n const adDir = join(root, 'adapters', axis, adapter)\n const adPath = join(adDir, 'adapter.json')\n if (!existsSync(adPath)) continue\n const ad = JSON.parse(readFileSync(adPath, 'utf8')) as { slots?: Record<string, string> }\n for (const [slot, file] of Object.entries(ad.slots ?? {})) {\n const fp = join(adDir, file)\n const content = norm(readFileSync(fp, 'utf8')).replace(/\\s+$/, '') + '\\n'\n slotProviders[slot] = { adapter, axis, source: rel(fp), content }\n }\n }\n\n const genPath = join(root, 'core/ai/skills', skill, 'SKILL.md')\n const generic = norm(readFileSync(genPath, 'utf8'))\n\n // Inputs = only files that actually compose THIS skill (generic + filled fragments).\n const inputs: InputRef[] = [{ path: rel(genPath), sha: sha(generic) }]\n const seenInput = new Set<string>([rel(genPath)])\n\n const lines = generic.split('\\n')\n const out: string[] = []\n const regions: Region[] = []\n let bodyLine = 0\n const push = (line: string, source: string, meta?: { adapter: string; slot: string }): void => {\n out.push(line)\n bodyLine++\n const last = regions[regions.length - 1]\n const slot = meta?.slot ?? null\n if (last && last.source === source && last.slot === slot && last.endLine === bodyLine - 1) {\n last.endLine = bodyLine\n } else {\n regions.push({ source, adapter: meta?.adapter ?? null, slot, startLine: bodyLine, endLine: bodyLine })\n }\n }\n\n let i = 0\n while (i < lines.length) {\n const current = lines[i] as string\n const open = current.match(OPEN)\n if (open) {\n const slot = open[1] as string\n let j = i + 1\n while (\n j < lines.length &&\n !(CLOSE.test(lines[j] as string) && (lines[j] as string).match(CLOSE)![1] === slot)\n )\n j++\n const provider = slotProviders[slot]\n if (provider) {\n if (!seenInput.has(provider.source)) {\n seenInput.add(provider.source)\n inputs.push({ path: provider.source, sha: sha(provider.content) })\n }\n for (const cl of provider.content.replace(/\\n$/, '').split('\\n')) {\n push(cl, provider.source, { adapter: provider.adapter, slot })\n }\n } // no provider (axis unselected, or active adapter omits this slot) -> prune\n i = j + 1\n continue\n }\n push(current, rel(genPath))\n i++\n }\n\n const sortedInputs = [...inputs].sort((a, b) => a.path.localeCompare(b.path))\n const digest = sha(JSON.stringify(sortedInputs))\n const header = `<!-- generated by aef render — do not hand-edit; use the improve-framework skill or edit the framework source. digest:${digest} -->`\n const rendered = header + '\\n\\n' + out.join('\\n') + '\\n'\n\n const manifest: RenderManifest = {\n skill,\n selection: selected,\n digest,\n note: 'region line numbers are body-relative (line 1 = first line after the 2-line header); digest covers consumed inputs only',\n inputs: sortedInputs,\n regions,\n }\n return { rendered, manifest, digest }\n}\n","// Typed contracts — the single source of truth for every config/adapter shape the\n// framework reads. zod gives us (1) runtime validation in the CLI, (2) inferred TS\n// types for the codebase, and (3) JSON Schema (see scripts/gen-schemas.ts) published\n// under schemas/ for editor/CI validation. Change a shape here and regenerate.\nimport { z } from 'zod'\n\nconst slotName = z\n .string()\n .regex(/^[a-z][\\w-]*\\.[a-z][\\w-]*$/, \"slot names are '<axis>.<key>', e.g. 'orm.cheatsheet'\")\n\n/** Per-consumer configuration the renderer, init/sync, and skills all read. */\nexport const FrameworkConfigSchema = z\n .object({\n $schema: z.string().optional(),\n projectName: z.string().describe('Substituted for {{PROJECT_NAME}} in templates.').optional(),\n harnesses: z\n .array(z.string())\n .min(1)\n .describe('Active harness adapters; each wires its files + skills dir.'),\n orm: z.string().nullable().describe('Selected ORM adapter, or null to omit ORM skills.').optional(),\n ui: z.string().nullable().optional(),\n stack: z.string().nullable().optional(),\n paths: z\n .object({\n modulesRoot: z.string().optional(),\n specsRoot: z.string().optional(),\n testsRoot: z.string().optional(),\n })\n .strict()\n .optional(),\n validation: z.array(z.string()).describe('Commands skills run as the verification gate.').optional(),\n git: z\n .object({\n defaultBranch: z.string().optional(),\n labels: z.array(z.string()).optional(),\n })\n .strict()\n .optional(),\n tiers: z\n .array(z.string())\n .describe('Opt-in tiers to install in addition to the defaults (e.g. [\"framework\", \"automation\"]).')\n .optional(),\n source: z\n .object({\n path: z\n .string()\n .nullable()\n .describe('Local checkout path; if null, clone repo on demand.')\n .optional(),\n repo: z.string().nullable().optional(),\n })\n .strict()\n .describe('Where improve-framework finds the framework SOURCE.')\n .optional(),\n feedback: z\n .object({\n capture: z.boolean().default(true).describe('Write scope-tagged lessons locally; zero egress.'),\n upstream: z\n .object({\n mode: z.enum(['scheduled-pr', 'prompt', 'off']).default('scheduled-pr'),\n channel: z.enum(['pr', 'issue', 'fork']).default('pr'),\n schedule: z.string().default('weekly'),\n sanitize: z.boolean().default(true),\n requireHumanApproval: z.boolean().default(true),\n })\n .strict()\n .optional(),\n })\n .strict()\n .optional(),\n })\n .strict()\n\n/** An adapter declares which skills it augments and the slot content it provides. */\nexport const AdapterSchema = z\n .object({\n $schema: z.string().optional(),\n name: z.string().describe(\"Adapter id, e.g. 'drizzle'.\"),\n axis: z.string().describe('Variation family: orm | ui | stack | harness.'),\n description: z.string().optional(),\n skillsDir: z.string().describe('Harness only: directory the per-skill links go in.').optional(),\n linkBase: z.string().describe('Harness only: relative link target base from skillsDir.').optional(),\n augments: z.array(z.string()).describe('Skill ids this adapter contributes slot content to.').optional(),\n slots: z\n .record(slotName, z.string())\n .describe('slotName -> fragment path, relative to the adapter dir.')\n .optional(),\n tiers: z\n .array(z.object({ skill: z.string(), tier: z.string() }).strict())\n .describe('Optional skills this adapter adds, and the tier each joins.')\n .optional(),\n })\n .strict()\n\n/** core/ai/skills/tiers.json — declares the default tier set and per-skill axis requirements. */\nexport const TiersSchema = z\n .object({\n default: z.array(z.string()),\n tiers: z.record(z.string(), z.object({ skills: z.array(z.string()) }).passthrough()),\n requires: z.record(z.string(), z.string()).optional(),\n })\n .passthrough()\n\nexport type FrameworkConfig = z.infer<typeof FrameworkConfigSchema>\nexport type Adapter = z.infer<typeof AdapterSchema>\nexport type Tiers = z.infer<typeof TiersSchema>\n","// Tier resolution — turns the configured axis selections into the converged skill set.\n// A skill whose required axis is unconfigured is skipped (reported, not errored).\nimport { readFileSync } from 'node:fs'\nimport { join } from 'node:path'\nimport type { FrameworkConfig, Tiers } from './contracts.js'\nimport { TiersSchema } from './contracts.js'\n\nexport interface SkillSelection {\n skills: string[]\n skipped: string[]\n}\n\nexport function loadTiers(root: string): Tiers {\n return TiersSchema.parse(JSON.parse(readFileSync(join(root, 'core/ai/skills/tiers.json'), 'utf8')))\n}\n\nexport function selectSkills(root: string, config: FrameworkConfig): SkillSelection {\n const tiers = loadTiers(root)\n const requires = tiers.requires ?? {}\n const skipped: string[] = []\n\n for (const t of config.tiers ?? [])\n if (!(t in tiers.tiers)) skipped.push(`tier '${t}' (unknown — not in tiers.json)`)\n\n const activeTiers = [...tiers.default, ...(config.tiers ?? [])]\n const candidates: string[] = []\n for (const t of activeTiers)\n for (const s of tiers.tiers[t]?.skills ?? []) if (!candidates.includes(s)) candidates.push(s)\n\n const skills: string[] = []\n for (const s of candidates) {\n const axis = requires[s]\n if (axis && !config[axis as keyof FrameworkConfig]) skipped.push(`${s} (needs ${axis})`)\n else skills.push(s)\n }\n return { skills: skills.sort(), skipped }\n}\n","// 3-way merge delegated to git — no custom merge engine. BASE = last render,\n// LOCAL = on-disk (with consumer edits), THEIRS = fresh framework render.\n// Returns the merged text and the conflict count git reports.\nimport { writeFileSync, mkdtempSync, rmSync } from 'node:fs'\nimport { join } from 'node:path'\nimport { tmpdir } from 'node:os'\nimport { spawnSync } from 'node:child_process'\n\nexport interface MergeResult {\n merged: string\n conflicts: number\n}\n\nexport function mergeFile(local: string, base: string, theirs: string): MergeResult {\n const dir = mkdtempSync(join(tmpdir(), 'agentic-merge-'))\n const lp = join(dir, 'local')\n const bp = join(dir, 'base')\n const tp = join(dir, 'theirs')\n writeFileSync(lp, local)\n writeFileSync(bp, base)\n writeFileSync(tp, theirs)\n const r = spawnSync(\n 'git',\n [\n 'merge-file',\n '-p',\n '-L',\n 'ours (your local edits)',\n '-L',\n 'base (last sync)',\n '-L',\n 'theirs (framework update)',\n lp,\n bp,\n tp,\n ],\n { encoding: 'utf8' },\n )\n rmSync(dir, { recursive: true, force: true })\n if (r.status === null || r.status < 0 || r.status >= 255)\n throw new Error(`git merge-file failed: ${r.stderr || String(r.error)}`)\n return { merged: r.stdout, conflicts: r.status }\n}\n"],"mappings":"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","names":["readFileSync","join","readFileSync","join","join"]}
|
package/dist/cli/index.js
CHANGED
|
@@ -2,15 +2,16 @@
|
|
|
2
2
|
import {
|
|
3
3
|
AdapterSchema,
|
|
4
4
|
FrameworkConfigSchema,
|
|
5
|
+
loadTiers,
|
|
5
6
|
mergeFile,
|
|
6
7
|
renderSkill,
|
|
7
8
|
selectSkills
|
|
8
|
-
} from "../chunk-
|
|
9
|
+
} from "../chunk-QEUDIAAQ.js";
|
|
9
10
|
|
|
10
11
|
// src/cli/index.ts
|
|
11
12
|
import { readFileSync as readFileSync8 } from "fs";
|
|
12
13
|
import { Command } from "commander";
|
|
13
|
-
import { ZodError } from "zod";
|
|
14
|
+
import { ZodError, ZodIssueCode } from "zod";
|
|
14
15
|
|
|
15
16
|
// src/cli/commands/init.ts
|
|
16
17
|
import { readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
@@ -71,7 +72,7 @@ function writeConventions(root, out, config) {
|
|
|
71
72
|
written.push(".ai/lessons.framework.md");
|
|
72
73
|
}
|
|
73
74
|
const outbox = join2(root, "core", "ai", "framework-feedback");
|
|
74
|
-
if (existsSync(outbox)) {
|
|
75
|
+
if (existsSync(outbox) && config.tiers?.includes("framework")) {
|
|
75
76
|
cpSync(outbox, join2(ai, "framework-feedback"), { recursive: true });
|
|
76
77
|
written.push(".ai/framework-feedback/");
|
|
77
78
|
}
|
|
@@ -99,9 +100,33 @@ function writeManifest(out, config, skills) {
|
|
|
99
100
|
mkdirSync(join2(out, ".ai"), { recursive: true });
|
|
100
101
|
writeFileSync(
|
|
101
102
|
join2(out, ".ai", ".render-manifest.json"),
|
|
102
|
-
JSON.stringify(
|
|
103
|
+
JSON.stringify(
|
|
104
|
+
{ selection: pick(config, ["orm", "ui", "stack", "harnesses", "tiers"]), skills },
|
|
105
|
+
null,
|
|
106
|
+
2
|
|
107
|
+
) + "\n"
|
|
103
108
|
);
|
|
104
109
|
}
|
|
110
|
+
function harnessSkillsDir(root, harness) {
|
|
111
|
+
const p2 = join2(root, "adapters", "harness", harness, "adapter.json");
|
|
112
|
+
if (!existsSync(p2)) return null;
|
|
113
|
+
const ad = AdapterSchema.parse(JSON.parse(readFileSync(p2, "utf8")));
|
|
114
|
+
return ad.skillsDir ?? null;
|
|
115
|
+
}
|
|
116
|
+
function wireNewSkills(root, out, config, skills) {
|
|
117
|
+
for (const harness of config.harnesses) {
|
|
118
|
+
const adPath = join2(root, "adapters", "harness", harness, "adapter.json");
|
|
119
|
+
if (!existsSync(adPath)) continue;
|
|
120
|
+
const ad = AdapterSchema.parse(JSON.parse(readFileSync(adPath, "utf8")));
|
|
121
|
+
if (!ad.skillsDir || !ad.linkBase) continue;
|
|
122
|
+
const hdir = join2(out, ad.skillsDir);
|
|
123
|
+
mkdirSync(hdir, { recursive: true });
|
|
124
|
+
for (const skill of skills) {
|
|
125
|
+
const link = join2(hdir, skill);
|
|
126
|
+
if (!existsSync(link) && !isLink(link)) symlinkSync(`${ad.linkBase}/${skill}`, link);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
105
130
|
function wireHarnesses(root, out, config, skills, useCopy) {
|
|
106
131
|
const aiSkills = join2(out, ".ai", "skills");
|
|
107
132
|
const wired = [];
|
|
@@ -180,7 +205,26 @@ async function runWizard(root) {
|
|
|
180
205
|
// src/cli/commands/init.ts
|
|
181
206
|
async function runInit(opts) {
|
|
182
207
|
const root = FRAMEWORK_ROOT;
|
|
183
|
-
|
|
208
|
+
if (opts.config && opts.interactive) {
|
|
209
|
+
throw new Error(
|
|
210
|
+
`--config and --interactive are mutually exclusive. Pass --config to use a file or --interactive to build one via prompts.`
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
if (!opts.config && !opts.interactive) {
|
|
214
|
+
throw new Error(
|
|
215
|
+
`--config is required.
|
|
216
|
+
|
|
217
|
+
Usage: aef init --config framework.config.json --out . --copy
|
|
218
|
+
|
|
219
|
+
To get started, create a framework.config.json. Minimum required:
|
|
220
|
+
{
|
|
221
|
+
"harnesses": ["claude-code"]
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
Run 'aef init --help' for all options.`
|
|
225
|
+
);
|
|
226
|
+
}
|
|
227
|
+
const raw = opts.interactive ? await runWizard(root) : JSON.parse(readFileSync2(opts.config, "utf8"));
|
|
184
228
|
const config = FrameworkConfigSchema.parse(raw);
|
|
185
229
|
const out = opts.out ?? join4(root, "examples/consumer");
|
|
186
230
|
const useCopy = Boolean(opts.copy);
|
|
@@ -204,7 +248,7 @@ async function runInit(opts) {
|
|
|
204
248
|
}
|
|
205
249
|
|
|
206
250
|
// src/cli/commands/sync.ts
|
|
207
|
-
import { readFileSync as readFileSync4, writeFileSync as writeFileSync4, existsSync as existsSync4 } from "fs";
|
|
251
|
+
import { readFileSync as readFileSync4, writeFileSync as writeFileSync4, existsSync as existsSync4, rmSync as rmSync2 } from "fs";
|
|
208
252
|
import { join as join6, relative as relative2 } from "path";
|
|
209
253
|
|
|
210
254
|
// src/cli/reconcile.ts
|
|
@@ -258,15 +302,32 @@ function runSync(opts) {
|
|
|
258
302
|
);
|
|
259
303
|
const manifestPath = join6(out, ".ai", ".render-manifest.json");
|
|
260
304
|
const manifest = JSON.parse(readFileSync4(manifestPath, "utf8"));
|
|
305
|
+
const { skills: desired } = selectSkills(root, config);
|
|
306
|
+
const desiredSet = new Set(desired);
|
|
307
|
+
const installed = Object.keys(manifest.skills);
|
|
308
|
+
const harnessDirs = /* @__PURE__ */ new Map();
|
|
309
|
+
for (const h of config.harnesses) harnessDirs.set(h, harnessSkillsDir(root, h));
|
|
310
|
+
for (const s of installed) {
|
|
311
|
+
if (desiredSet.has(s)) continue;
|
|
312
|
+
rmSync2(join6(out, ".ai", "skills", s), { recursive: true, force: true });
|
|
313
|
+
rmSync2(join6(out, ".ai", ".base", s), { recursive: true, force: true });
|
|
314
|
+
delete manifest.skills[s];
|
|
315
|
+
for (const dir of harnessDirs.values())
|
|
316
|
+
if (dir) rmSync2(join6(out, dir, s), { recursive: true, force: true });
|
|
317
|
+
}
|
|
261
318
|
const report = [];
|
|
262
319
|
let conflicts = 0;
|
|
263
|
-
|
|
320
|
+
const newSkills = [];
|
|
321
|
+
for (const skill of desired) {
|
|
322
|
+
const isNew = !manifest.skills[skill];
|
|
264
323
|
const r = reconcileSkill(root, out, config, skill);
|
|
265
324
|
manifest.skills[skill] = { digest: r.digest, inputs: r.inputs };
|
|
266
325
|
conflicts += r.conflicts;
|
|
267
326
|
report.push(REPORT[r.status](skill));
|
|
327
|
+
if (isNew) newSkills.push(skill);
|
|
268
328
|
}
|
|
269
|
-
|
|
329
|
+
if (newSkills.length > 0) wireNewSkills(root, out, config, newSkills);
|
|
330
|
+
writeManifest(out, config, manifest.skills);
|
|
270
331
|
console.log(`Synced ${relative2(process.cwd(), out) || "."} from framework source`);
|
|
271
332
|
const fwLessonsSrc = join6(root, "core", "ai", "lessons.framework.md");
|
|
272
333
|
if (existsSync4(fwLessonsSrc)) {
|
|
@@ -288,7 +349,7 @@ ${conflicts} conflict(s) written as <<<<<<< markers. Review with 'git diff', res
|
|
|
288
349
|
}
|
|
289
350
|
|
|
290
351
|
// src/cli/commands/dev.ts
|
|
291
|
-
import { readFileSync as readFileSync5, readdirSync as readdirSync2, existsSync as existsSync5, mkdirSync as mkdirSync2, rmSync as
|
|
352
|
+
import { readFileSync as readFileSync5, readdirSync as readdirSync2, existsSync as existsSync5, mkdirSync as mkdirSync2, rmSync as rmSync3, symlinkSync as symlinkSync2 } from "fs";
|
|
292
353
|
import { join as join7, relative as relative3 } from "path";
|
|
293
354
|
function runDev() {
|
|
294
355
|
const root = FRAMEWORK_ROOT;
|
|
@@ -311,7 +372,7 @@ function runDev() {
|
|
|
311
372
|
const target = relative3(hdir, devSkillsDir);
|
|
312
373
|
for (const skill of devSkills) {
|
|
313
374
|
const link = join7(hdir, skill);
|
|
314
|
-
if (existsSync5(link) || isLink(link))
|
|
375
|
+
if (existsSync5(link) || isLink(link)) rmSync3(link, { recursive: true, force: true });
|
|
315
376
|
symlinkSync2(join7(target, skill), link);
|
|
316
377
|
}
|
|
317
378
|
wired.push(`${harness} -> ${ad.skillsDir}`);
|
|
@@ -326,10 +387,17 @@ function runDev() {
|
|
|
326
387
|
import { readFileSync as readFileSync6, writeFileSync as writeFileSync5, mkdirSync as mkdirSync3 } from "fs";
|
|
327
388
|
import { join as join8, relative as relative4 } from "path";
|
|
328
389
|
function runRender(opts) {
|
|
390
|
+
if (!opts.config) {
|
|
391
|
+
throw new Error(
|
|
392
|
+
`--config is required.
|
|
393
|
+
|
|
394
|
+
Usage: aef render --skill <name> --config framework.config.json
|
|
395
|
+
|
|
396
|
+
Run 'aef render --help' for all options.`
|
|
397
|
+
);
|
|
398
|
+
}
|
|
329
399
|
const root = FRAMEWORK_ROOT;
|
|
330
|
-
const config = FrameworkConfigSchema.parse(
|
|
331
|
-
JSON.parse(readFileSync6(opts.config ?? join8(root, "framework.config.example.json"), "utf8"))
|
|
332
|
-
);
|
|
400
|
+
const config = FrameworkConfigSchema.parse(JSON.parse(readFileSync6(opts.config, "utf8")));
|
|
333
401
|
const { rendered, manifest, digest } = renderSkill(root, config, opts.skill);
|
|
334
402
|
if (opts.out) {
|
|
335
403
|
const dest = join8(opts.out, opts.skill);
|
|
@@ -351,7 +419,7 @@ function runRender(opts) {
|
|
|
351
419
|
}
|
|
352
420
|
|
|
353
421
|
// src/cli/commands/adapter.ts
|
|
354
|
-
import { readFileSync as readFileSync7, writeFileSync as writeFileSync6, existsSync as existsSync6, rmSync as
|
|
422
|
+
import { readFileSync as readFileSync7, writeFileSync as writeFileSync6, existsSync as existsSync6, rmSync as rmSync4, cpSync as cpSync2 } from "fs";
|
|
355
423
|
import { join as join9, relative as relative5 } from "path";
|
|
356
424
|
var AXES = ["orm", "ui", "stack", "harness"];
|
|
357
425
|
function resolveAxis(root, name) {
|
|
@@ -360,12 +428,6 @@ function resolveAxis(root, name) {
|
|
|
360
428
|
}
|
|
361
429
|
throw new Error(`no adapter '${name}' found under adapters/{${AXES.join(",")}}/`);
|
|
362
430
|
}
|
|
363
|
-
function harnessSkillsDir(root, harness) {
|
|
364
|
-
const p2 = join9(root, "adapters", "harness", harness, "adapter.json");
|
|
365
|
-
if (!existsSync6(p2)) return null;
|
|
366
|
-
const ad = AdapterSchema.parse(JSON.parse(readFileSync7(p2, "utf8")));
|
|
367
|
-
return ad.skillsDir ?? null;
|
|
368
|
-
}
|
|
369
431
|
function runAdd(name, opts) {
|
|
370
432
|
mutate(name, "add", opts);
|
|
371
433
|
}
|
|
@@ -378,29 +440,59 @@ function mutate(name, op, opts) {
|
|
|
378
440
|
const useCopy = Boolean(opts.copy);
|
|
379
441
|
const cfgPath = join9(out, "framework.config.json");
|
|
380
442
|
const raw = JSON.parse(readFileSync7(cfgPath, "utf8"));
|
|
381
|
-
const
|
|
382
|
-
const prevHarnesses = [...
|
|
383
|
-
|
|
384
|
-
|
|
443
|
+
const prevConfig = FrameworkConfigSchema.parse(raw);
|
|
444
|
+
const prevHarnesses = [...prevConfig.harnesses ?? []];
|
|
445
|
+
const tierDef = loadTiers(root);
|
|
446
|
+
const isTier = name in tierDef.tiers;
|
|
447
|
+
if (isTier) {
|
|
448
|
+
if (tierDef.default.includes(name))
|
|
449
|
+
throw new Error(
|
|
450
|
+
`tier '${name}' is a default tier \u2014 it is always active and cannot be ${op === "add" ? "explicitly opted in" : "removed"}`
|
|
451
|
+
);
|
|
452
|
+
const current = prevConfig.tiers ?? [];
|
|
385
453
|
if (op === "add") {
|
|
386
|
-
|
|
454
|
+
if (!current.includes(name)) raw.tiers = [...current, name];
|
|
387
455
|
} else {
|
|
388
|
-
if (!
|
|
389
|
-
|
|
390
|
-
|
|
456
|
+
if (!current.includes(name)) throw new Error(`tier '${name}' is not enabled; nothing to remove`);
|
|
457
|
+
const after = current.filter((t) => t !== name);
|
|
458
|
+
if (after.length > 0) raw.tiers = after;
|
|
459
|
+
else delete raw.tiers;
|
|
391
460
|
}
|
|
392
|
-
raw.harnesses = [...list];
|
|
393
|
-
} else if (op === "add") {
|
|
394
|
-
raw[axis] = name;
|
|
395
461
|
} else {
|
|
396
|
-
|
|
397
|
-
|
|
462
|
+
const axis = resolveAxis(root, name);
|
|
463
|
+
if (axis === "harness") {
|
|
464
|
+
const list = new Set(prevHarnesses);
|
|
465
|
+
if (op === "add") {
|
|
466
|
+
list.add(name);
|
|
467
|
+
} else {
|
|
468
|
+
if (!list.has(name)) throw new Error(`harness '${name}' is not installed; nothing to remove`);
|
|
469
|
+
if (list.size === 1) throw new Error("cannot remove the last harness \u2014 at least one is required");
|
|
470
|
+
list.delete(name);
|
|
471
|
+
}
|
|
472
|
+
raw.harnesses = [...list];
|
|
473
|
+
} else if (op === "add") {
|
|
474
|
+
raw[axis] = name;
|
|
475
|
+
} else {
|
|
476
|
+
if (raw[axis] !== name)
|
|
477
|
+
throw new Error(`'${name}' is not the active ${axis} adapter; nothing to remove`);
|
|
478
|
+
raw[axis] = null;
|
|
479
|
+
}
|
|
398
480
|
}
|
|
399
481
|
const config = FrameworkConfigSchema.parse(raw);
|
|
400
482
|
writeFileSync6(cfgPath, JSON.stringify(raw, null, 2) + "\n");
|
|
483
|
+
if (isTier && name === "framework") {
|
|
484
|
+
const outboxDst = join9(out, ".ai", "framework-feedback");
|
|
485
|
+
if (op === "add") {
|
|
486
|
+
const outboxSrc = join9(root, "core", "ai", "framework-feedback");
|
|
487
|
+
if (existsSync6(outboxSrc)) cpSync2(outboxSrc, outboxDst, { recursive: true });
|
|
488
|
+
} else {
|
|
489
|
+
rmSync4(outboxDst, { recursive: true, force: true });
|
|
490
|
+
}
|
|
491
|
+
}
|
|
401
492
|
const conflicts = reconcile(root, out, config, prevHarnesses, useCopy);
|
|
493
|
+
const kind = isTier ? "tier" : "adapter";
|
|
402
494
|
console.log(
|
|
403
|
-
`${op === "add" ? "Added" : "Removed"} ${name} (${
|
|
495
|
+
`${op === "add" ? "Added" : "Removed"} ${name} (${kind}) in ${relative5(process.cwd(), out) || "."}`
|
|
404
496
|
);
|
|
405
497
|
if (conflicts) {
|
|
406
498
|
console.log(
|
|
@@ -421,11 +513,11 @@ function reconcile(root, out, config, prevHarnesses, useCopy) {
|
|
|
421
513
|
dirByHarness.set(h, harnessSkillsDir(root, h));
|
|
422
514
|
for (const s of installed) {
|
|
423
515
|
if (selectedSet.has(s)) continue;
|
|
424
|
-
|
|
425
|
-
|
|
516
|
+
rmSync4(join9(out, ".ai", "skills", s), { recursive: true, force: true });
|
|
517
|
+
rmSync4(join9(out, ".ai", ".base", s), { recursive: true, force: true });
|
|
426
518
|
delete manifest.skills[s];
|
|
427
519
|
for (const dir of dirByHarness.values())
|
|
428
|
-
if (dir)
|
|
520
|
+
if (dir) rmSync4(join9(out, dir, s), { recursive: true, force: true });
|
|
429
521
|
}
|
|
430
522
|
let conflicts = 0;
|
|
431
523
|
for (const s of selected) {
|
|
@@ -436,7 +528,7 @@ function reconcile(root, out, config, prevHarnesses, useCopy) {
|
|
|
436
528
|
for (const h of prevHarnesses) {
|
|
437
529
|
if ((config.harnesses ?? []).includes(h)) continue;
|
|
438
530
|
const dir = dirByHarness.get(h);
|
|
439
|
-
if (dir && existsSync6(join9(out, dir)))
|
|
531
|
+
if (dir && existsSync6(join9(out, dir))) rmSync4(join9(out, dir), { recursive: true, force: true });
|
|
440
532
|
}
|
|
441
533
|
wireHarnesses(root, out, config, selected, useCopy);
|
|
442
534
|
writeManifest(out, config, manifest.skills);
|
|
@@ -445,18 +537,55 @@ function reconcile(root, out, config, prevHarnesses, useCopy) {
|
|
|
445
537
|
|
|
446
538
|
// src/cli/index.ts
|
|
447
539
|
var { version } = JSON.parse(readFileSync8(new URL("../../package.json", import.meta.url), "utf8"));
|
|
540
|
+
function levenshtein(a, b) {
|
|
541
|
+
const dp = Array.from({ length: b.length + 1 }, (_, j) => j);
|
|
542
|
+
for (let i = 1; i <= a.length; i++) {
|
|
543
|
+
let prev = dp[0];
|
|
544
|
+
dp[0] = i;
|
|
545
|
+
for (let j = 1; j <= b.length; j++) {
|
|
546
|
+
const temp = dp[j];
|
|
547
|
+
dp[j] = a[i - 1] === b[j - 1] ? prev : 1 + Math.min(prev, temp, dp[j - 1]);
|
|
548
|
+
prev = temp;
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
return dp[b.length];
|
|
552
|
+
}
|
|
553
|
+
function suggestKey(unknown, valid) {
|
|
554
|
+
let best = null;
|
|
555
|
+
let bestDist = Infinity;
|
|
556
|
+
for (const k of valid) {
|
|
557
|
+
const d = levenshtein(unknown, k);
|
|
558
|
+
if (d < bestDist) {
|
|
559
|
+
bestDist = d;
|
|
560
|
+
best = k;
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
return bestDist / Math.max(unknown.length, best.length) <= 0.4 ? best : null;
|
|
564
|
+
}
|
|
448
565
|
var program = new Command();
|
|
449
566
|
program.name("aef").description("Render slot-based engineering skills into a consumer repo and keep them in sync.").version(version);
|
|
450
|
-
program.command("init").description("Render the configured skill set into a consumer repo and wire harnesses.").option("--config <path>", "path to framework.config.json (
|
|
451
|
-
program.command("render").description("Render a single skill to stdout (or --out <dir>) for inspection.").requiredOption("--skill <name>", "skill id to render").option("--config <path>", "path to framework.config.json (
|
|
567
|
+
program.command("init").description("Render the configured skill set into a consumer repo and wire harnesses.").option("--config <path>", "path to framework.config.json (required unless --interactive)").option("--out <dir>", "consumer directory to write into").option("--copy", "copy rendered skills into harness dirs instead of symlinking").option("-i, --interactive", "build the config interactively via prompts").action((opts) => runInit(opts));
|
|
568
|
+
program.command("render").description("Render a single skill to stdout (or --out <dir>) for inspection.").requiredOption("--skill <name>", "skill id to render").option("--config <path>", "path to framework.config.json (required)").option("--out <dir>", "write SKILL.md + provenance.json under <dir>/<skill>/ instead of stdout").action((opts) => runRender(opts));
|
|
452
569
|
program.command("sync").description("Re-render from framework source and reconcile with local edits (3-way merge).").option("--out <dir>", "consumer directory to sync").action((opts) => runSync(opts));
|
|
453
570
|
program.command("add").argument("<adapter>", "adapter name to select (axis inferred from its adapter.json)").description("Select an adapter and reconcile the installed skill set (merges local edits).").option("--out <dir>", "consumer directory to update").option("--copy", "copy rendered skills into harness dirs instead of symlinking").action((adapter, opts) => runAdd(adapter, opts));
|
|
454
571
|
program.command("remove").argument("<adapter>", "adapter name to deselect (axis inferred from its adapter.json)").description("Deselect an adapter; uninstalls skills that required its axis.").option("--out <dir>", "consumer directory to update").option("--copy", "copy rendered skills into harness dirs instead of symlinking").action((adapter, opts) => runRemove(adapter, opts));
|
|
455
572
|
program.command("dev").description("Meta-install: wire this repo\u2019s harness dirs to dev/ skills for framework development.").action(() => runDev());
|
|
573
|
+
var validRootKeys = Object.keys(FrameworkConfigSchema.shape);
|
|
456
574
|
program.parseAsync(process.argv).catch((err) => {
|
|
457
575
|
if (err instanceof ZodError) {
|
|
458
576
|
console.error("Invalid configuration:");
|
|
459
|
-
for (const issue of err.issues)
|
|
577
|
+
for (const issue of err.issues) {
|
|
578
|
+
if (issue.code === ZodIssueCode.unrecognized_keys && issue.path.length === 0) {
|
|
579
|
+
for (const key of issue.keys) {
|
|
580
|
+
const suggestion = suggestKey(key, validRootKeys);
|
|
581
|
+
const hint = suggestion != null ? ` Did you mean '${suggestion}'?` : "";
|
|
582
|
+
console.error(` - Unknown key '${key}'.${hint}`);
|
|
583
|
+
}
|
|
584
|
+
console.error(` Valid keys: ${validRootKeys.join(", ")}`);
|
|
585
|
+
} else {
|
|
586
|
+
console.error(` - ${issue.path.join(".") || "(root)"}: ${issue.message}`);
|
|
587
|
+
}
|
|
588
|
+
}
|
|
460
589
|
} else {
|
|
461
590
|
console.error(err instanceof Error ? err.message : String(err));
|
|
462
591
|
}
|
package/dist/cli/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/cli/index.ts","../../src/cli/commands/init.ts","../../src/cli/root.ts","../../src/cli/consumer-io.ts","../../src/cli/wizard.ts","../../src/cli/commands/sync.ts","../../src/cli/reconcile.ts","../../src/cli/commands/dev.ts","../../src/cli/commands/render.ts","../../src/cli/commands/adapter.ts"],"sourcesContent":["#!/usr/bin/env node\n// aef — CLI for the Agentic Engineering Framework.\n//\n// aef init [--config <cfg>] [--out <dir>] [--copy] [--interactive]\n// aef sync [--out <dir>]\n// aef add <adapter> [--out <dir>] [--copy]\n// aef remove <adapter> [--out <dir>] [--copy]\n// aef dev\nimport { readFileSync } from 'node:fs'\nimport { Command } from 'commander'\nimport { ZodError } from 'zod'\nimport { runInit } from './commands/init.js'\nimport { runSync } from './commands/sync.js'\nimport { runDev } from './commands/dev.js'\nimport { runRender } from './commands/render.js'\nimport { runAdd, runRemove } from './commands/adapter.js'\n\n// Single source of truth for the version: read the package's own package.json at\n// runtime so it never drifts from release-please's bump (dev: src/cli/, built:\n// dist/cli/ — both resolve to the package root).\nconst { version } = JSON.parse(readFileSync(new URL('../../package.json', import.meta.url), 'utf8')) as {\n version: string\n}\n\nconst program = new Command()\n\nprogram\n .name('aef')\n .description('Render slot-based engineering skills into a consumer repo and keep them in sync.')\n .version(version)\n\nprogram\n .command('init')\n .description('Render the configured skill set into a consumer repo and wire harnesses.')\n .option('--config <path>', 'path to framework.config.json (defaults to the bundled example)')\n .option('--out <dir>', 'consumer directory to write into')\n .option('--copy', 'copy rendered skills into harness dirs instead of symlinking')\n .option('-i, --interactive', 'build the config interactively via prompts')\n .action((opts) => runInit(opts))\n\nprogram\n .command('render')\n .description('Render a single skill to stdout (or --out <dir>) for inspection.')\n .requiredOption('--skill <name>', 'skill id to render')\n .option('--config <path>', 'path to framework.config.json (defaults to the bundled example)')\n .option('--out <dir>', 'write SKILL.md + provenance.json under <dir>/<skill>/ instead of stdout')\n .action((opts) => runRender(opts))\n\nprogram\n .command('sync')\n .description('Re-render from framework source and reconcile with local edits (3-way merge).')\n .option('--out <dir>', 'consumer directory to sync')\n .action((opts) => runSync(opts))\n\nprogram\n .command('add')\n .argument('<adapter>', 'adapter name to select (axis inferred from its adapter.json)')\n .description('Select an adapter and reconcile the installed skill set (merges local edits).')\n .option('--out <dir>', 'consumer directory to update')\n .option('--copy', 'copy rendered skills into harness dirs instead of symlinking')\n .action((adapter, opts) => runAdd(adapter, opts))\n\nprogram\n .command('remove')\n .argument('<adapter>', 'adapter name to deselect (axis inferred from its adapter.json)')\n .description('Deselect an adapter; uninstalls skills that required its axis.')\n .option('--out <dir>', 'consumer directory to update')\n .option('--copy', 'copy rendered skills into harness dirs instead of symlinking')\n .action((adapter, opts) => runRemove(adapter, opts))\n\nprogram\n .command('dev')\n .description('Meta-install: wire this repo’s harness dirs to dev/ skills for framework development.')\n .action(() => runDev())\n\nprogram.parseAsync(process.argv).catch((err: unknown) => {\n if (err instanceof ZodError) {\n console.error('Invalid configuration:')\n for (const issue of err.issues) console.error(` - ${issue.path.join('.') || '(root)'}: ${issue.message}`)\n } else {\n console.error(err instanceof Error ? err.message : String(err))\n }\n process.exit(1)\n})\n","// `aef init` — render the configured skill set into <out>/.ai/skills/, snapshot a\n// BASE under <out>/.ai/.base/, write the render manifest (sync's base), persist the\n// resolved config, and wire each harness.\nimport { readFileSync, writeFileSync } from 'node:fs'\nimport { join, relative } from 'node:path'\nimport { FrameworkConfigSchema } from '../../core/contracts.js'\nimport { renderSkill } from '../../core/render.js'\nimport { selectSkills } from '../../core/select.js'\nimport { FRAMEWORK_ROOT } from '../root.js'\nimport {\n writeSkill,\n writeBase,\n writeManifest,\n wireHarnesses,\n writeConventions,\n type ManifestSkills,\n} from '../consumer-io.js'\nimport { runWizard } from '../wizard.js'\n\nexport interface InitOptions {\n config?: string\n out?: string\n copy?: boolean\n interactive?: boolean\n}\n\nexport async function runInit(opts: InitOptions): Promise<void> {\n const root = FRAMEWORK_ROOT\n\n // `raw` is what we persist to framework.config.json (byte-stable); `config` is the\n // zod-validated view the renderer consumes.\n const raw: unknown = opts.interactive\n ? await runWizard(root)\n : JSON.parse(readFileSync(opts.config ?? join(root, 'framework.config.example.json'), 'utf8'))\n const config = FrameworkConfigSchema.parse(raw)\n\n const out = opts.out ?? join(root, 'examples/consumer')\n const useCopy = Boolean(opts.copy)\n\n const { skills, skipped } = selectSkills(root, config)\n\n const manifestSkills: ManifestSkills = {}\n for (const skill of skills) {\n const { rendered, manifest, digest } = renderSkill(root, config, skill)\n writeSkill(out, skill, rendered, manifest)\n writeBase(out, skill, rendered)\n manifestSkills[skill] = { digest, inputs: manifest.inputs }\n }\n writeManifest(out, config, manifestSkills)\n writeFileSync(join(out, 'framework.config.json'), JSON.stringify(raw, null, 2) + '\\n')\n\n const conventions = writeConventions(root, out, config)\n const wired = wireHarnesses(root, out, config, skills, useCopy)\n\n console.log(`Initialised agentic framework into ${relative(process.cwd(), out) || '.'}`)\n console.log(` skills installed: ${skills.join(', ') || '(none)'}`)\n console.log(` conventions: ${conventions.join(', ')}`)\n if (skipped.length) console.log(` skipped (axis not configured): ${skipped.join(', ')}`)\n console.log(` harnesses wired: ${wired.join(' | ') || '(none)'}`)\n}\n","import { fileURLToPath } from 'node:url'\nimport { dirname, join } from 'node:path'\n\n// The framework SOURCE root (where core/, adapters/, schemas/ live). Resolves the\n// same whether running from src/cli/ via tsx or from dist/cli/ after a build —\n// both are two levels below the package root.\nexport const FRAMEWORK_ROOT = join(dirname(fileURLToPath(import.meta.url)), '..', '..')\n","// Filesystem side of init/sync: writing a consumer's .ai/ tree and wiring harnesses.\n// Kept separate from the command wiring so the behaviour is unit-testable.\nimport {\n readFileSync,\n writeFileSync,\n mkdirSync,\n existsSync,\n lstatSync,\n rmSync,\n cpSync,\n symlinkSync,\n} from 'node:fs'\nimport { join } from 'node:path'\nimport { AdapterSchema, type FrameworkConfig } from '../core/contracts.js'\nimport type { InputRef, RenderManifest } from '../core/render.js'\n\nexport const isLink = (p: string): boolean => {\n try {\n return lstatSync(p).isSymbolicLink()\n } catch {\n return false\n }\n}\n\nexport function pick<T extends Record<string, unknown>>(o: T, keys: string[]): Record<string, unknown> {\n const r: Record<string, unknown> = {}\n for (const k of keys) if (k in o) r[k] = o[k]\n return r\n}\n\n/**\n * Install the generic `core/ai` conventions into a consumer: the specs/qa/runs scaffolding,\n * a starter lessons.md, a CLAUDE.md, and AGENTS.md rendered from the template with\n * {{PROJECT_NAME}} substituted. Idempotent — safe to re-run. Returns the paths written.\n */\nexport function writeConventions(root: string, out: string, config: FrameworkConfig): string[] {\n const projectName = config.projectName ?? 'your project'\n const sub = (s: string): string => s.split('{{PROJECT_NAME}}').join(projectName)\n const ai = join(out, '.ai')\n mkdirSync(ai, { recursive: true })\n const written: string[] = []\n\n for (const dir of ['specs', 'qa', 'runs']) {\n const src = join(root, 'core', 'ai', dir)\n if (existsSync(src)) {\n cpSync(src, join(ai, dir), { recursive: true })\n written.push(`.ai/${dir}/`)\n }\n }\n // Substitute {{PROJECT_NAME}} in the one convention file that carries it.\n const specsReadme = join(ai, 'specs', 'README.md')\n if (existsSync(specsReadme)) writeFileSync(specsReadme, sub(readFileSync(specsReadme, 'utf8')))\n\n const lessonsSrc = join(root, 'core', 'ai', 'lessons.md')\n if (existsSync(lessonsSrc)) {\n writeFileSync(join(ai, 'lessons.md'), sub(readFileSync(lessonsSrc, 'utf8')))\n written.push('.ai/lessons.md')\n }\n // Synced-read-only generic lessons + the local-only framework-feedback outbox (decision #8).\n const fwLessons = join(root, 'core', 'ai', 'lessons.framework.md')\n if (existsSync(fwLessons)) {\n writeFileSync(join(ai, 'lessons.framework.md'), readFileSync(fwLessons, 'utf8'))\n written.push('.ai/lessons.framework.md')\n }\n const outbox = join(root, 'core', 'ai', 'framework-feedback')\n if (existsSync(outbox)) {\n cpSync(outbox, join(ai, 'framework-feedback'), { recursive: true })\n written.push('.ai/framework-feedback/')\n }\n\n const tpl = join(root, 'core', 'AGENTS.md.template')\n if (existsSync(tpl)) {\n writeFileSync(join(out, 'AGENTS.md'), sub(readFileSync(tpl, 'utf8')))\n written.push('AGENTS.md')\n }\n writeFileSync(join(out, 'CLAUDE.md'), '@AGENTS.md\\n')\n written.push('CLAUDE.md')\n return written\n}\n\nexport function writeSkill(out: string, skill: string, rendered: string, manifest: RenderManifest): void {\n const dest = join(out, '.ai', 'skills', skill)\n mkdirSync(dest, { recursive: true })\n writeFileSync(join(dest, 'SKILL.md'), rendered)\n writeFileSync(join(dest, 'provenance.json'), JSON.stringify(manifest, null, 2) + '\\n')\n}\n\nexport function writeBase(out: string, skill: string, rendered: string): void {\n const d = join(out, '.ai', '.base', skill)\n mkdirSync(d, { recursive: true })\n writeFileSync(join(d, 'SKILL.md'), rendered)\n}\n\nexport type ManifestSkills = Record<string, { digest: string; inputs: InputRef[] }>\n\nexport function writeManifest(out: string, config: FrameworkConfig, skills: ManifestSkills): void {\n mkdirSync(join(out, '.ai'), { recursive: true })\n writeFileSync(\n join(out, '.ai', '.render-manifest.json'),\n JSON.stringify({ selection: pick(config, ['orm', 'ui', 'stack', 'harnesses']), skills }, null, 2) + '\\n',\n )\n}\n\nexport function wireHarnesses(\n root: string,\n out: string,\n config: FrameworkConfig,\n skills: string[],\n useCopy: boolean,\n): string[] {\n const aiSkills = join(out, '.ai', 'skills')\n const wired: string[] = []\n for (const harness of config.harnesses) {\n const adPath = join(root, 'adapters', 'harness', harness, 'adapter.json')\n if (!existsSync(adPath)) {\n console.warn(`! no harness adapter '${harness}', skipping`)\n continue\n }\n const ad = AdapterSchema.parse(JSON.parse(readFileSync(adPath, 'utf8')))\n if (!ad.skillsDir || !ad.linkBase) {\n console.warn(`! harness adapter '${harness}' is missing skillsDir/linkBase, skipping`)\n continue\n }\n const hdir = join(out, ad.skillsDir)\n mkdirSync(hdir, { recursive: true })\n for (const skill of skills) {\n const link = join(hdir, skill)\n if (existsSync(link) || isLink(link)) rmSync(link, { recursive: true, force: true })\n if (useCopy) cpSync(join(aiSkills, skill), link, { recursive: true })\n else symlinkSync(`${ad.linkBase}/${skill}`, link)\n }\n wired.push(`${harness} -> ${ad.skillsDir} (${useCopy ? 'copy' : 'symlink'})`)\n }\n return wired\n}\n","// Interactive `init` wizard (opt-in via --interactive). Discovers the available\n// adapters on disk and builds a framework.config object via @clack/prompts.\nimport { readdirSync, existsSync } from 'node:fs'\nimport { join } from 'node:path'\nimport * as p from '@clack/prompts'\n\nfunction listAdapters(root: string, axis: string): string[] {\n const dir = join(root, 'adapters', axis)\n if (!existsSync(dir)) return []\n return readdirSync(dir).filter((n) => existsSync(join(dir, n, 'adapter.json')))\n}\n\nfunction bail<T>(value: T | symbol): T {\n if (p.isCancel(value)) {\n p.cancel('Cancelled — nothing written.')\n process.exit(1)\n }\n return value as T\n}\n\nconst axisOptions = (root: string, axis: string): { value: string | null; label: string }[] => [\n { value: null, label: 'none' },\n ...listAdapters(root, axis).map((v) => ({ value: v, label: v })),\n]\n\nexport async function runWizard(root: string): Promise<Record<string, unknown>> {\n p.intro('aef init')\n\n const projectName = bail(\n await p.text({ message: 'Project name', placeholder: 'my-app', defaultValue: 'my-app' }),\n )\n const harnesses = bail(\n await p.multiselect({\n message: 'Which AI harnesses should be wired?',\n options: listAdapters(root, 'harness').map((v) => ({ value: v, label: v })),\n required: true,\n }),\n )\n const orm = bail(\n await p.select({ message: 'ORM adapter', options: axisOptions(root, 'orm'), initialValue: null }),\n )\n const ui = bail(\n await p.select({ message: 'UI adapter', options: axisOptions(root, 'ui'), initialValue: null }),\n )\n\n p.outro('Configuration ready.')\n\n return {\n $schema: './schemas/framework.config.schema.json',\n projectName,\n harnesses,\n orm,\n ui,\n }\n}\n","// `aef sync` — re-render from the (updated) framework source and reconcile with\n// local edits via a git-native 3-way merge (BASE = last render, LOCAL = on-disk,\n// NEW = fresh render). Exit code 2 signals unresolved conflicts written to the tree.\nimport { readFileSync, writeFileSync, existsSync } from 'node:fs'\nimport { join, relative } from 'node:path'\nimport { FrameworkConfigSchema } from '../../core/contracts.js'\nimport { FRAMEWORK_ROOT } from '../root.js'\nimport { reconcileSkill, type ReconcileStatus } from '../reconcile.js'\nimport type { ManifestSkills } from '../consumer-io.js'\n\ninterface RenderManifestFile {\n selection: unknown\n skills: ManifestSkills\n}\n\nconst REPORT: Record<ReconcileStatus, (s: string) => string> = {\n installed: (s) => ` + ${s}: installed`,\n unchanged: (s) => ` = ${s}: framework unchanged`,\n forwarded: (s) => ` ↑ ${s}: updated (no local edits)`,\n merged: (s) => ` ⇄ ${s}: merged local edits + framework update (clean)`,\n conflict: (s) => ` ⇄ ${s}: merged — CONFLICT(S), resolve in working tree`,\n}\n\nexport interface SyncOptions {\n out?: string\n}\n\nexport function runSync(opts: SyncOptions): void {\n const root = FRAMEWORK_ROOT\n const out = opts.out ?? join(root, 'examples/consumer')\n const config = FrameworkConfigSchema.parse(\n JSON.parse(readFileSync(join(out, 'framework.config.json'), 'utf8')),\n )\n const manifestPath = join(out, '.ai', '.render-manifest.json')\n const manifest = JSON.parse(readFileSync(manifestPath, 'utf8')) as RenderManifestFile\n\n const report: string[] = []\n let conflicts = 0\n for (const skill of Object.keys(manifest.skills)) {\n const r = reconcileSkill(root, out, config, skill)\n manifest.skills[skill] = { digest: r.digest, inputs: r.inputs }\n conflicts += r.conflicts\n report.push(REPORT[r.status](skill))\n }\n writeFileSync(manifestPath, JSON.stringify(manifest, null, 2) + '\\n')\n\n console.log(`Synced ${relative(process.cwd(), out) || '.'} from framework source`)\n // Refresh synced read-only framework lessons (loop closure, decision #8).\n const fwLessonsSrc = join(root, 'core', 'ai', 'lessons.framework.md')\n if (existsSync(fwLessonsSrc)) {\n const dest = join(out, '.ai', 'lessons.framework.md')\n const next = readFileSync(fwLessonsSrc, 'utf8')\n if (!existsSync(dest) || readFileSync(dest, 'utf8') !== next) {\n writeFileSync(dest, next)\n report.push(' ↑ lessons.framework.md: refreshed (synced, read-only)')\n }\n }\n\n report.forEach((l) => console.log(l))\n if (conflicts) {\n console.log(\n `\\n${conflicts} conflict(s) written as <<<<<<< markers. Review with 'git diff', resolve, commit.`,\n )\n process.exitCode = 2\n }\n}\n","// Shared per-skill reconcile: render a skill from the current framework source and\n// fold the result into a consumer, preserving local edits via a git-native 3-way merge.\n// Used by both `aef sync` and `aef add`/`remove` so the reconcile semantics —\n// fast-forward, clean merge, conflict, and provenance refresh — live in exactly one place.\nimport { readFileSync, writeFileSync, existsSync } from 'node:fs'\nimport { join } from 'node:path'\nimport { renderSkill, type InputRef } from '../core/render.js'\nimport { mergeFile } from '../core/merge.js'\nimport type { FrameworkConfig } from '../core/contracts.js'\nimport { writeSkill, writeBase } from './consumer-io.js'\n\nexport type ReconcileStatus = 'installed' | 'unchanged' | 'forwarded' | 'merged' | 'conflict'\n\nexport interface ReconcileResult {\n status: ReconcileStatus\n digest: string\n inputs: InputRef[]\n conflicts: number\n}\n\n/**\n * Reconcile one skill in `out` against the current render:\n * - not yet on disk → install fresh (+ BASE),\n * - framework unchanged → leave LOCAL alone (local edits kept),\n * - framework changed, no edits → fast-forward to NEW,\n * - both changed → 3-way merge (conflicts land as <<<<<<< markers).\n * Always refreshes provenance.json to the fresh render and returns the new digest/inputs\n * so the caller can update the render manifest.\n */\nexport function reconcileSkill(\n root: string,\n out: string,\n config: FrameworkConfig,\n skill: string,\n): ReconcileResult {\n const { rendered: NEW, manifest, digest } = renderSkill(root, config, skill)\n const skillMd = join(out, '.ai', 'skills', skill, 'SKILL.md')\n\n if (!existsSync(skillMd)) {\n writeSkill(out, skill, NEW, manifest)\n writeBase(out, skill, NEW)\n return { status: 'installed', digest, inputs: manifest.inputs, conflicts: 0 }\n }\n\n const baseMd = join(out, '.ai', '.base', skill, 'SKILL.md')\n const BASE = existsSync(baseMd) ? readFileSync(baseMd, 'utf8') : NEW\n const LOCAL = readFileSync(skillMd, 'utf8')\n\n let status: ReconcileStatus = 'unchanged'\n let conflicts = 0\n if (NEW !== BASE) {\n if (LOCAL === BASE) {\n writeFileSync(skillMd, NEW)\n status = 'forwarded'\n } else {\n const { merged, conflicts: n } = mergeFile(LOCAL, BASE, NEW)\n writeFileSync(skillMd, merged)\n conflicts = n\n status = n ? 'conflict' : 'merged'\n }\n writeBase(out, skill, NEW)\n }\n // Provenance always tracks the fresh render (improve-framework reads it to route edits).\n writeFileSync(\n join(out, '.ai', 'skills', skill, 'provenance.json'),\n JSON.stringify(manifest, null, 2) + '\\n',\n )\n return { status, digest, inputs: manifest.inputs, conflicts }\n}\n","// `aef dev` — the \"meta\" install for developing THIS framework. Wires the repo's\n// own harness skill dirs to dev/ skills (source symlinks). Installs the toolchain, not\n// the shipped product; harness dirs are gitignored.\nimport { readFileSync, readdirSync, existsSync, mkdirSync, rmSync, symlinkSync } from 'node:fs'\nimport { join, relative } from 'node:path'\nimport { AdapterSchema } from '../../core/contracts.js'\nimport { FRAMEWORK_ROOT } from '../root.js'\nimport { isLink } from '../consumer-io.js'\n\nexport function runDev(): void {\n const root = FRAMEWORK_ROOT\n const devSkillsDir = join(root, 'dev', 'skills')\n if (!existsSync(devSkillsDir)) {\n console.error('no dev/skills/ found')\n process.exit(1)\n }\n const devSkills = readdirSync(devSkillsDir).filter((d) => existsSync(join(devSkillsDir, d, 'SKILL.md')))\n const harnessRoot = join(root, 'adapters', 'harness')\n const harnesses = readdirSync(harnessRoot).filter((d) => existsSync(join(harnessRoot, d, 'adapter.json')))\n\n const wired: string[] = []\n for (const harness of harnesses) {\n const ad = AdapterSchema.parse(\n JSON.parse(readFileSync(join(harnessRoot, harness, 'adapter.json'), 'utf8')),\n )\n if (!ad.skillsDir) continue\n const hdir = join(root, ad.skillsDir)\n mkdirSync(hdir, { recursive: true })\n const target = relative(hdir, devSkillsDir) // robust relative link target\n for (const skill of devSkills) {\n const link = join(hdir, skill)\n if (existsSync(link) || isLink(link)) rmSync(link, { recursive: true, force: true })\n symlinkSync(join(target, skill), link)\n }\n wired.push(`${harness} -> ${ad.skillsDir}`)\n }\n console.log('Framework dev install (meta):')\n console.log(` dev skills: ${devSkills.join(', ') || '(none)'}`)\n console.log(` harnesses : ${wired.join(' | ')}`)\n console.log(' (harness dirs are gitignored; re-run after adding a dev skill)')\n}\n","// `aef render` — render a single skill to stdout (or --out dir) for inspection.\n// The lightweight counterpart to `init`; handy while authoring skills/adapters and\n// the render step the improve-framework skill points at.\nimport { readFileSync, writeFileSync, mkdirSync } from 'node:fs'\nimport { join, relative } from 'node:path'\nimport { FrameworkConfigSchema } from '../../core/contracts.js'\nimport { renderSkill } from '../../core/render.js'\nimport { FRAMEWORK_ROOT } from '../root.js'\n\nexport interface RenderOptions {\n skill: string\n config?: string\n out?: string\n}\n\nexport function runRender(opts: RenderOptions): void {\n const root = FRAMEWORK_ROOT\n const config = FrameworkConfigSchema.parse(\n JSON.parse(readFileSync(opts.config ?? join(root, 'framework.config.example.json'), 'utf8')),\n )\n const { rendered, manifest, digest } = renderSkill(root, config, opts.skill)\n\n if (opts.out) {\n const dest = join(opts.out, opts.skill)\n mkdirSync(dest, { recursive: true })\n writeFileSync(join(dest, 'SKILL.md'), rendered)\n writeFileSync(join(dest, 'provenance.json'), JSON.stringify(manifest, null, 2) + '\\n')\n console.error(\n `Rendered '${opts.skill}' (orm=${manifest.selection.orm ?? 'none'}) -> ${relative(root, dest)}`,\n )\n console.error(\n ` digest ${digest} · ${manifest.regions.length} regions · ${manifest.inputs.length} inputs`,\n )\n } else {\n // Body to stdout (pipeable); summary to stderr.\n process.stdout.write(rendered)\n console.error(\n ` digest ${digest} · ${manifest.regions.length} regions · ${manifest.inputs.length} inputs`,\n )\n }\n}\n","// `aef add <adapter>` / `aef remove <adapter>` — change an axis selection in a\n// consumer's framework.config.json and reconcile the installed skill set:\n// • newly-selected skills are rendered fresh (+ BASE snapshot),\n// • skills no longer selected are uninstalled (skill dir, BASE, harness links),\n// • surviving skills are 3-way merged (like sync) so adapter-content changes flow in\n// without clobbering local edits.\n// The adapter's axis is read from its adapter.json, so the command is `add <name>`.\nimport { readFileSync, writeFileSync, existsSync, rmSync } from 'node:fs'\nimport { join, relative } from 'node:path'\nimport { FrameworkConfigSchema, AdapterSchema, type FrameworkConfig } from '../../core/contracts.js'\nimport { selectSkills } from '../../core/select.js'\nimport { FRAMEWORK_ROOT } from '../root.js'\nimport { writeManifest, wireHarnesses, type ManifestSkills } from '../consumer-io.js'\nimport { reconcileSkill } from '../reconcile.js'\n\nconst AXES = ['orm', 'ui', 'stack', 'harness'] as const\n\ninterface ManifestFile {\n selection: unknown\n skills: ManifestSkills\n}\n\nexport interface AdapterCmdOptions {\n out?: string\n copy?: boolean\n}\n\n/** Find which axis an adapter name belongs to by locating its adapter.json on disk. */\nfunction resolveAxis(root: string, name: string): (typeof AXES)[number] {\n for (const axis of AXES) {\n if (existsSync(join(root, 'adapters', axis, name, 'adapter.json'))) return axis\n }\n throw new Error(`no adapter '${name}' found under adapters/{${AXES.join(',')}}/`)\n}\n\nfunction harnessSkillsDir(root: string, harness: string): string | null {\n const p = join(root, 'adapters', 'harness', harness, 'adapter.json')\n if (!existsSync(p)) return null\n const ad = AdapterSchema.parse(JSON.parse(readFileSync(p, 'utf8')))\n return ad.skillsDir ?? null\n}\n\nexport function runAdd(name: string, opts: AdapterCmdOptions): void {\n mutate(name, 'add', opts)\n}\n\nexport function runRemove(name: string, opts: AdapterCmdOptions): void {\n mutate(name, 'remove', opts)\n}\n\nfunction mutate(name: string, op: 'add' | 'remove', opts: AdapterCmdOptions): void {\n const root = FRAMEWORK_ROOT\n const out = opts.out ?? join(root, 'examples/consumer')\n const useCopy = Boolean(opts.copy)\n const cfgPath = join(out, 'framework.config.json')\n\n const raw = JSON.parse(readFileSync(cfgPath, 'utf8')) as Record<string, unknown>\n const axis = resolveAxis(root, name)\n const prevHarnesses = [...(FrameworkConfigSchema.parse(raw).harnesses ?? [])]\n\n if (axis === 'harness') {\n const list = new Set(prevHarnesses)\n if (op === 'add') {\n list.add(name)\n } else {\n if (!list.has(name)) throw new Error(`harness '${name}' is not installed; nothing to remove`)\n if (list.size === 1) throw new Error('cannot remove the last harness — at least one is required')\n list.delete(name)\n }\n raw.harnesses = [...list]\n } else if (op === 'add') {\n raw[axis] = name\n } else {\n // remove: only clear the axis if this adapter is the one selected\n if (raw[axis] !== name) throw new Error(`'${name}' is not the active ${axis} adapter; nothing to remove`)\n raw[axis] = null\n }\n\n const config = FrameworkConfigSchema.parse(raw)\n writeFileSync(cfgPath, JSON.stringify(raw, null, 2) + '\\n')\n\n const conflicts = reconcile(root, out, config, prevHarnesses, useCopy)\n console.log(\n `${op === 'add' ? 'Added' : 'Removed'} ${name} (${axis}) in ${relative(process.cwd(), out) || '.'}`,\n )\n if (conflicts) {\n console.log(\n `\\n${conflicts} conflict(s) written as <<<<<<< markers — review with 'git diff', resolve, commit.`,\n )\n process.exitCode = 2\n }\n}\n\nfunction reconcile(\n root: string,\n out: string,\n config: FrameworkConfig,\n prevHarnesses: string[],\n useCopy: boolean,\n): number {\n const manifestPath = join(out, '.ai', '.render-manifest.json')\n const manifest = JSON.parse(readFileSync(manifestPath, 'utf8')) as ManifestFile\n\n const { skills: selected } = selectSkills(root, config)\n const selectedSet = new Set(selected)\n const installed = Object.keys(manifest.skills)\n\n // Resolve each harness's skills dir once (used when removing skills and harnesses).\n const dirByHarness = new Map<string, string | null>()\n for (const h of new Set([...prevHarnesses, ...(config.harnesses ?? [])]))\n dirByHarness.set(h, harnessSkillsDir(root, h))\n\n // 1. Uninstall skills no longer selected.\n for (const s of installed) {\n if (selectedSet.has(s)) continue\n rmSync(join(out, '.ai', 'skills', s), { recursive: true, force: true })\n rmSync(join(out, '.ai', '.base', s), { recursive: true, force: true })\n delete manifest.skills[s]\n for (const dir of dirByHarness.values())\n if (dir) rmSync(join(out, dir, s), { recursive: true, force: true })\n }\n\n // 2. Install new + 3-way-merge surviving skills (shared with `sync`).\n let conflicts = 0\n for (const s of selected) {\n const r = reconcileSkill(root, out, config, s)\n manifest.skills[s] = { digest: r.digest, inputs: r.inputs }\n conflicts += r.conflicts\n }\n\n // 3. Drop skills dirs for harnesses removed entirely, then re-wire the surviving set.\n for (const h of prevHarnesses) {\n if ((config.harnesses ?? []).includes(h)) continue\n const dir = dirByHarness.get(h)\n if (dir && existsSync(join(out, dir))) rmSync(join(out, dir), { recursive: true, force: true })\n }\n wireHarnesses(root, out, config, selected, useCopy)\n\n writeManifest(out, config, manifest.skills)\n return conflicts\n}\n"],"mappings":";;;;;;;;;;AAQA,SAAS,gBAAAA,qBAAoB;AAC7B,SAAS,eAAe;AACxB,SAAS,gBAAgB;;;ACPzB,SAAS,gBAAAC,eAAc,iBAAAC,sBAAqB;AAC5C,SAAS,QAAAC,OAAM,gBAAgB;;;ACJ/B,SAAS,qBAAqB;AAC9B,SAAS,SAAS,YAAY;AAKvB,IAAM,iBAAiB,KAAK,QAAQ,cAAc,YAAY,GAAG,CAAC,GAAG,MAAM,IAAI;;;ACJtF;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,QAAAC,aAAY;AAId,IAAM,SAAS,CAACC,OAAuB;AAC5C,MAAI;AACF,WAAO,UAAUA,EAAC,EAAE,eAAe;AAAA,EACrC,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEO,SAAS,KAAwC,GAAM,MAAyC;AACrG,QAAM,IAA6B,CAAC;AACpC,aAAW,KAAK,KAAM,KAAI,KAAK,EAAG,GAAE,CAAC,IAAI,EAAE,CAAC;AAC5C,SAAO;AACT;AAOO,SAAS,iBAAiB,MAAc,KAAa,QAAmC;AAC7F,QAAM,cAAc,OAAO,eAAe;AAC1C,QAAM,MAAM,CAAC,MAAsB,EAAE,MAAM,kBAAkB,EAAE,KAAK,WAAW;AAC/E,QAAM,KAAKC,MAAK,KAAK,KAAK;AAC1B,YAAU,IAAI,EAAE,WAAW,KAAK,CAAC;AACjC,QAAM,UAAoB,CAAC;AAE3B,aAAW,OAAO,CAAC,SAAS,MAAM,MAAM,GAAG;AACzC,UAAM,MAAMA,MAAK,MAAM,QAAQ,MAAM,GAAG;AACxC,QAAI,WAAW,GAAG,GAAG;AACnB,aAAO,KAAKA,MAAK,IAAI,GAAG,GAAG,EAAE,WAAW,KAAK,CAAC;AAC9C,cAAQ,KAAK,OAAO,GAAG,GAAG;AAAA,IAC5B;AAAA,EACF;AAEA,QAAM,cAAcA,MAAK,IAAI,SAAS,WAAW;AACjD,MAAI,WAAW,WAAW,EAAG,eAAc,aAAa,IAAI,aAAa,aAAa,MAAM,CAAC,CAAC;AAE9F,QAAM,aAAaA,MAAK,MAAM,QAAQ,MAAM,YAAY;AACxD,MAAI,WAAW,UAAU,GAAG;AAC1B,kBAAcA,MAAK,IAAI,YAAY,GAAG,IAAI,aAAa,YAAY,MAAM,CAAC,CAAC;AAC3E,YAAQ,KAAK,gBAAgB;AAAA,EAC/B;AAEA,QAAM,YAAYA,MAAK,MAAM,QAAQ,MAAM,sBAAsB;AACjE,MAAI,WAAW,SAAS,GAAG;AACzB,kBAAcA,MAAK,IAAI,sBAAsB,GAAG,aAAa,WAAW,MAAM,CAAC;AAC/E,YAAQ,KAAK,0BAA0B;AAAA,EACzC;AACA,QAAM,SAASA,MAAK,MAAM,QAAQ,MAAM,oBAAoB;AAC5D,MAAI,WAAW,MAAM,GAAG;AACtB,WAAO,QAAQA,MAAK,IAAI,oBAAoB,GAAG,EAAE,WAAW,KAAK,CAAC;AAClE,YAAQ,KAAK,yBAAyB;AAAA,EACxC;AAEA,QAAM,MAAMA,MAAK,MAAM,QAAQ,oBAAoB;AACnD,MAAI,WAAW,GAAG,GAAG;AACnB,kBAAcA,MAAK,KAAK,WAAW,GAAG,IAAI,aAAa,KAAK,MAAM,CAAC,CAAC;AACpE,YAAQ,KAAK,WAAW;AAAA,EAC1B;AACA,gBAAcA,MAAK,KAAK,WAAW,GAAG,cAAc;AACpD,UAAQ,KAAK,WAAW;AACxB,SAAO;AACT;AAEO,SAAS,WAAW,KAAa,OAAe,UAAkB,UAAgC;AACvG,QAAM,OAAOA,MAAK,KAAK,OAAO,UAAU,KAAK;AAC7C,YAAU,MAAM,EAAE,WAAW,KAAK,CAAC;AACnC,gBAAcA,MAAK,MAAM,UAAU,GAAG,QAAQ;AAC9C,gBAAcA,MAAK,MAAM,iBAAiB,GAAG,KAAK,UAAU,UAAU,MAAM,CAAC,IAAI,IAAI;AACvF;AAEO,SAAS,UAAU,KAAa,OAAe,UAAwB;AAC5E,QAAM,IAAIA,MAAK,KAAK,OAAO,SAAS,KAAK;AACzC,YAAU,GAAG,EAAE,WAAW,KAAK,CAAC;AAChC,gBAAcA,MAAK,GAAG,UAAU,GAAG,QAAQ;AAC7C;AAIO,SAAS,cAAc,KAAa,QAAyB,QAA8B;AAChG,YAAUA,MAAK,KAAK,KAAK,GAAG,EAAE,WAAW,KAAK,CAAC;AAC/C;AAAA,IACEA,MAAK,KAAK,OAAO,uBAAuB;AAAA,IACxC,KAAK,UAAU,EAAE,WAAW,KAAK,QAAQ,CAAC,OAAO,MAAM,SAAS,WAAW,CAAC,GAAG,OAAO,GAAG,MAAM,CAAC,IAAI;AAAA,EACtG;AACF;AAEO,SAAS,cACd,MACA,KACA,QACA,QACA,SACU;AACV,QAAM,WAAWA,MAAK,KAAK,OAAO,QAAQ;AAC1C,QAAM,QAAkB,CAAC;AACzB,aAAW,WAAW,OAAO,WAAW;AACtC,UAAM,SAASA,MAAK,MAAM,YAAY,WAAW,SAAS,cAAc;AACxE,QAAI,CAAC,WAAW,MAAM,GAAG;AACvB,cAAQ,KAAK,yBAAyB,OAAO,aAAa;AAC1D;AAAA,IACF;AACA,UAAM,KAAK,cAAc,MAAM,KAAK,MAAM,aAAa,QAAQ,MAAM,CAAC,CAAC;AACvE,QAAI,CAAC,GAAG,aAAa,CAAC,GAAG,UAAU;AACjC,cAAQ,KAAK,sBAAsB,OAAO,2CAA2C;AACrF;AAAA,IACF;AACA,UAAM,OAAOA,MAAK,KAAK,GAAG,SAAS;AACnC,cAAU,MAAM,EAAE,WAAW,KAAK,CAAC;AACnC,eAAW,SAAS,QAAQ;AAC1B,YAAM,OAAOA,MAAK,MAAM,KAAK;AAC7B,UAAI,WAAW,IAAI,KAAK,OAAO,IAAI,EAAG,QAAO,MAAM,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AACnF,UAAI,QAAS,QAAOA,MAAK,UAAU,KAAK,GAAG,MAAM,EAAE,WAAW,KAAK,CAAC;AAAA,UAC/D,aAAY,GAAG,GAAG,QAAQ,IAAI,KAAK,IAAI,IAAI;AAAA,IAClD;AACA,UAAM,KAAK,GAAG,OAAO,OAAO,GAAG,SAAS,KAAK,UAAU,SAAS,SAAS,GAAG;AAAA,EAC9E;AACA,SAAO;AACT;;;ACpIA,SAAS,aAAa,cAAAC,mBAAkB;AACxC,SAAS,QAAAC,aAAY;AACrB,YAAY,OAAO;AAEnB,SAAS,aAAa,MAAc,MAAwB;AAC1D,QAAM,MAAMA,MAAK,MAAM,YAAY,IAAI;AACvC,MAAI,CAACD,YAAW,GAAG,EAAG,QAAO,CAAC;AAC9B,SAAO,YAAY,GAAG,EAAE,OAAO,CAAC,MAAMA,YAAWC,MAAK,KAAK,GAAG,cAAc,CAAC,CAAC;AAChF;AAEA,SAAS,KAAQ,OAAsB;AACrC,MAAM,WAAS,KAAK,GAAG;AACrB,IAAE,SAAO,mCAA8B;AACvC,YAAQ,KAAK,CAAC;AAAA,EAChB;AACA,SAAO;AACT;AAEA,IAAM,cAAc,CAAC,MAAc,SAA4D;AAAA,EAC7F,EAAE,OAAO,MAAM,OAAO,OAAO;AAAA,EAC7B,GAAG,aAAa,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,EAAE,EAAE;AACjE;AAEA,eAAsB,UAAU,MAAgD;AAC9E,EAAE,QAAM,UAAU;AAElB,QAAM,cAAc;AAAA,IAClB,MAAQ,OAAK,EAAE,SAAS,gBAAgB,aAAa,UAAU,cAAc,SAAS,CAAC;AAAA,EACzF;AACA,QAAM,YAAY;AAAA,IAChB,MAAQ,cAAY;AAAA,MAClB,SAAS;AAAA,MACT,SAAS,aAAa,MAAM,SAAS,EAAE,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,EAAE,EAAE;AAAA,MAC1E,UAAU;AAAA,IACZ,CAAC;AAAA,EACH;AACA,QAAM,MAAM;AAAA,IACV,MAAQ,SAAO,EAAE,SAAS,eAAe,SAAS,YAAY,MAAM,KAAK,GAAG,cAAc,KAAK,CAAC;AAAA,EAClG;AACA,QAAM,KAAK;AAAA,IACT,MAAQ,SAAO,EAAE,SAAS,cAAc,SAAS,YAAY,MAAM,IAAI,GAAG,cAAc,KAAK,CAAC;AAAA,EAChG;AAEA,EAAE,QAAM,sBAAsB;AAE9B,SAAO;AAAA,IACL,SAAS;AAAA,IACT;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;;;AH5BA,eAAsB,QAAQ,MAAkC;AAC9D,QAAM,OAAO;AAIb,QAAM,MAAe,KAAK,cACtB,MAAM,UAAU,IAAI,IACpB,KAAK,MAAMC,cAAa,KAAK,UAAUC,MAAK,MAAM,+BAA+B,GAAG,MAAM,CAAC;AAC/F,QAAM,SAAS,sBAAsB,MAAM,GAAG;AAE9C,QAAM,MAAM,KAAK,OAAOA,MAAK,MAAM,mBAAmB;AACtD,QAAM,UAAU,QAAQ,KAAK,IAAI;AAEjC,QAAM,EAAE,QAAQ,QAAQ,IAAI,aAAa,MAAM,MAAM;AAErD,QAAM,iBAAiC,CAAC;AACxC,aAAW,SAAS,QAAQ;AAC1B,UAAM,EAAE,UAAU,UAAU,OAAO,IAAI,YAAY,MAAM,QAAQ,KAAK;AACtE,eAAW,KAAK,OAAO,UAAU,QAAQ;AACzC,cAAU,KAAK,OAAO,QAAQ;AAC9B,mBAAe,KAAK,IAAI,EAAE,QAAQ,QAAQ,SAAS,OAAO;AAAA,EAC5D;AACA,gBAAc,KAAK,QAAQ,cAAc;AACzC,EAAAC,eAAcD,MAAK,KAAK,uBAAuB,GAAG,KAAK,UAAU,KAAK,MAAM,CAAC,IAAI,IAAI;AAErF,QAAM,cAAc,iBAAiB,MAAM,KAAK,MAAM;AACtD,QAAM,QAAQ,cAAc,MAAM,KAAK,QAAQ,QAAQ,OAAO;AAE9D,UAAQ,IAAI,sCAAsC,SAAS,QAAQ,IAAI,GAAG,GAAG,KAAK,GAAG,EAAE;AACvF,UAAQ,IAAI,uBAAuB,OAAO,KAAK,IAAI,KAAK,QAAQ,EAAE;AAClE,UAAQ,IAAI,kBAAkB,YAAY,KAAK,IAAI,CAAC,EAAE;AACtD,MAAI,QAAQ,OAAQ,SAAQ,IAAI,oCAAoC,QAAQ,KAAK,IAAI,CAAC,EAAE;AACxF,UAAQ,IAAI,sBAAsB,MAAM,KAAK,KAAK,KAAK,QAAQ,EAAE;AACnE;;;AIxDA,SAAS,gBAAAE,eAAc,iBAAAC,gBAAe,cAAAC,mBAAkB;AACxD,SAAS,QAAAC,OAAM,YAAAC,iBAAgB;;;ACA/B,SAAS,gBAAAC,eAAc,iBAAAC,gBAAe,cAAAC,mBAAkB;AACxD,SAAS,QAAAC,aAAY;AAwBd,SAAS,eACd,MACA,KACA,QACA,OACiB;AACjB,QAAM,EAAE,UAAU,KAAK,UAAU,OAAO,IAAI,YAAY,MAAM,QAAQ,KAAK;AAC3E,QAAM,UAAUC,MAAK,KAAK,OAAO,UAAU,OAAO,UAAU;AAE5D,MAAI,CAACC,YAAW,OAAO,GAAG;AACxB,eAAW,KAAK,OAAO,KAAK,QAAQ;AACpC,cAAU,KAAK,OAAO,GAAG;AACzB,WAAO,EAAE,QAAQ,aAAa,QAAQ,QAAQ,SAAS,QAAQ,WAAW,EAAE;AAAA,EAC9E;AAEA,QAAM,SAASD,MAAK,KAAK,OAAO,SAAS,OAAO,UAAU;AAC1D,QAAM,OAAOC,YAAW,MAAM,IAAIC,cAAa,QAAQ,MAAM,IAAI;AACjE,QAAM,QAAQA,cAAa,SAAS,MAAM;AAE1C,MAAI,SAA0B;AAC9B,MAAI,YAAY;AAChB,MAAI,QAAQ,MAAM;AAChB,QAAI,UAAU,MAAM;AAClB,MAAAC,eAAc,SAAS,GAAG;AAC1B,eAAS;AAAA,IACX,OAAO;AACL,YAAM,EAAE,QAAQ,WAAW,EAAE,IAAI,UAAU,OAAO,MAAM,GAAG;AAC3D,MAAAA,eAAc,SAAS,MAAM;AAC7B,kBAAY;AACZ,eAAS,IAAI,aAAa;AAAA,IAC5B;AACA,cAAU,KAAK,OAAO,GAAG;AAAA,EAC3B;AAEA,EAAAA;AAAA,IACEH,MAAK,KAAK,OAAO,UAAU,OAAO,iBAAiB;AAAA,IACnD,KAAK,UAAU,UAAU,MAAM,CAAC,IAAI;AAAA,EACtC;AACA,SAAO,EAAE,QAAQ,QAAQ,QAAQ,SAAS,QAAQ,UAAU;AAC9D;;;ADrDA,IAAM,SAAyD;AAAA,EAC7D,WAAW,CAAC,MAAM,OAAO,CAAC;AAAA,EAC1B,WAAW,CAAC,MAAM,OAAO,CAAC;AAAA,EAC1B,WAAW,CAAC,MAAM,YAAO,CAAC;AAAA,EAC1B,QAAQ,CAAC,MAAM,YAAO,CAAC;AAAA,EACvB,UAAU,CAAC,MAAM,YAAO,CAAC;AAC3B;AAMO,SAAS,QAAQ,MAAyB;AAC/C,QAAM,OAAO;AACb,QAAM,MAAM,KAAK,OAAOI,MAAK,MAAM,mBAAmB;AACtD,QAAM,SAAS,sBAAsB;AAAA,IACnC,KAAK,MAAMC,cAAaD,MAAK,KAAK,uBAAuB,GAAG,MAAM,CAAC;AAAA,EACrE;AACA,QAAM,eAAeA,MAAK,KAAK,OAAO,uBAAuB;AAC7D,QAAM,WAAW,KAAK,MAAMC,cAAa,cAAc,MAAM,CAAC;AAE9D,QAAM,SAAmB,CAAC;AAC1B,MAAI,YAAY;AAChB,aAAW,SAAS,OAAO,KAAK,SAAS,MAAM,GAAG;AAChD,UAAM,IAAI,eAAe,MAAM,KAAK,QAAQ,KAAK;AACjD,aAAS,OAAO,KAAK,IAAI,EAAE,QAAQ,EAAE,QAAQ,QAAQ,EAAE,OAAO;AAC9D,iBAAa,EAAE;AACf,WAAO,KAAK,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC;AAAA,EACrC;AACA,EAAAC,eAAc,cAAc,KAAK,UAAU,UAAU,MAAM,CAAC,IAAI,IAAI;AAEpE,UAAQ,IAAI,UAAUC,UAAS,QAAQ,IAAI,GAAG,GAAG,KAAK,GAAG,wBAAwB;AAEjF,QAAM,eAAeH,MAAK,MAAM,QAAQ,MAAM,sBAAsB;AACpE,MAAII,YAAW,YAAY,GAAG;AAC5B,UAAM,OAAOJ,MAAK,KAAK,OAAO,sBAAsB;AACpD,UAAM,OAAOC,cAAa,cAAc,MAAM;AAC9C,QAAI,CAACG,YAAW,IAAI,KAAKH,cAAa,MAAM,MAAM,MAAM,MAAM;AAC5D,MAAAC,eAAc,MAAM,IAAI;AACxB,aAAO,KAAK,8DAAyD;AAAA,IACvE;AAAA,EACF;AAEA,SAAO,QAAQ,CAAC,MAAM,QAAQ,IAAI,CAAC,CAAC;AACpC,MAAI,WAAW;AACb,YAAQ;AAAA,MACN;AAAA,EAAK,SAAS;AAAA,IAChB;AACA,YAAQ,WAAW;AAAA,EACrB;AACF;;;AE9DA,SAAS,gBAAAG,eAAc,eAAAC,cAAa,cAAAC,aAAY,aAAAC,YAAW,UAAAC,SAAQ,eAAAC,oBAAmB;AACtF,SAAS,QAAAC,OAAM,YAAAC,iBAAgB;AAKxB,SAAS,SAAe;AAC7B,QAAM,OAAO;AACb,QAAM,eAAeC,MAAK,MAAM,OAAO,QAAQ;AAC/C,MAAI,CAACC,YAAW,YAAY,GAAG;AAC7B,YAAQ,MAAM,sBAAsB;AACpC,YAAQ,KAAK,CAAC;AAAA,EAChB;AACA,QAAM,YAAYC,aAAY,YAAY,EAAE,OAAO,CAAC,MAAMD,YAAWD,MAAK,cAAc,GAAG,UAAU,CAAC,CAAC;AACvG,QAAM,cAAcA,MAAK,MAAM,YAAY,SAAS;AACpD,QAAM,YAAYE,aAAY,WAAW,EAAE,OAAO,CAAC,MAAMD,YAAWD,MAAK,aAAa,GAAG,cAAc,CAAC,CAAC;AAEzG,QAAM,QAAkB,CAAC;AACzB,aAAW,WAAW,WAAW;AAC/B,UAAM,KAAK,cAAc;AAAA,MACvB,KAAK,MAAMG,cAAaH,MAAK,aAAa,SAAS,cAAc,GAAG,MAAM,CAAC;AAAA,IAC7E;AACA,QAAI,CAAC,GAAG,UAAW;AACnB,UAAM,OAAOA,MAAK,MAAM,GAAG,SAAS;AACpC,IAAAI,WAAU,MAAM,EAAE,WAAW,KAAK,CAAC;AACnC,UAAM,SAASC,UAAS,MAAM,YAAY;AAC1C,eAAW,SAAS,WAAW;AAC7B,YAAM,OAAOL,MAAK,MAAM,KAAK;AAC7B,UAAIC,YAAW,IAAI,KAAK,OAAO,IAAI,EAAG,CAAAK,QAAO,MAAM,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AACnF,MAAAC,aAAYP,MAAK,QAAQ,KAAK,GAAG,IAAI;AAAA,IACvC;AACA,UAAM,KAAK,GAAG,OAAO,OAAO,GAAG,SAAS,EAAE;AAAA,EAC5C;AACA,UAAQ,IAAI,+BAA+B;AAC3C,UAAQ,IAAI,iBAAiB,UAAU,KAAK,IAAI,KAAK,QAAQ,EAAE;AAC/D,UAAQ,IAAI,iBAAiB,MAAM,KAAK,KAAK,CAAC,EAAE;AAChD,UAAQ,IAAI,kEAAkE;AAChF;;;ACrCA,SAAS,gBAAAQ,eAAc,iBAAAC,gBAAe,aAAAC,kBAAiB;AACvD,SAAS,QAAAC,OAAM,YAAAC,iBAAgB;AAWxB,SAAS,UAAU,MAA2B;AACnD,QAAM,OAAO;AACb,QAAM,SAAS,sBAAsB;AAAA,IACnC,KAAK,MAAMC,cAAa,KAAK,UAAUC,MAAK,MAAM,+BAA+B,GAAG,MAAM,CAAC;AAAA,EAC7F;AACA,QAAM,EAAE,UAAU,UAAU,OAAO,IAAI,YAAY,MAAM,QAAQ,KAAK,KAAK;AAE3E,MAAI,KAAK,KAAK;AACZ,UAAM,OAAOA,MAAK,KAAK,KAAK,KAAK,KAAK;AACtC,IAAAC,WAAU,MAAM,EAAE,WAAW,KAAK,CAAC;AACnC,IAAAC,eAAcF,MAAK,MAAM,UAAU,GAAG,QAAQ;AAC9C,IAAAE,eAAcF,MAAK,MAAM,iBAAiB,GAAG,KAAK,UAAU,UAAU,MAAM,CAAC,IAAI,IAAI;AACrF,YAAQ;AAAA,MACN,aAAa,KAAK,KAAK,UAAU,SAAS,UAAU,OAAO,MAAM,QAAQG,UAAS,MAAM,IAAI,CAAC;AAAA,IAC/F;AACA,YAAQ;AAAA,MACN,YAAY,MAAM,SAAM,SAAS,QAAQ,MAAM,iBAAc,SAAS,OAAO,MAAM;AAAA,IACrF;AAAA,EACF,OAAO;AAEL,YAAQ,OAAO,MAAM,QAAQ;AAC7B,YAAQ;AAAA,MACN,YAAY,MAAM,SAAM,SAAS,QAAQ,MAAM,iBAAc,SAAS,OAAO,MAAM;AAAA,IACrF;AAAA,EACF;AACF;;;ACjCA,SAAS,gBAAAC,eAAc,iBAAAC,gBAAe,cAAAC,aAAY,UAAAC,eAAc;AAChE,SAAS,QAAAC,OAAM,YAAAC,iBAAgB;AAO/B,IAAM,OAAO,CAAC,OAAO,MAAM,SAAS,SAAS;AAa7C,SAAS,YAAY,MAAc,MAAqC;AACtE,aAAW,QAAQ,MAAM;AACvB,QAAIC,YAAWC,MAAK,MAAM,YAAY,MAAM,MAAM,cAAc,CAAC,EAAG,QAAO;AAAA,EAC7E;AACA,QAAM,IAAI,MAAM,eAAe,IAAI,2BAA2B,KAAK,KAAK,GAAG,CAAC,IAAI;AAClF;AAEA,SAAS,iBAAiB,MAAc,SAAgC;AACtE,QAAMC,KAAID,MAAK,MAAM,YAAY,WAAW,SAAS,cAAc;AACnE,MAAI,CAACD,YAAWE,EAAC,EAAG,QAAO;AAC3B,QAAM,KAAK,cAAc,MAAM,KAAK,MAAMC,cAAaD,IAAG,MAAM,CAAC,CAAC;AAClE,SAAO,GAAG,aAAa;AACzB;AAEO,SAAS,OAAO,MAAc,MAA+B;AAClE,SAAO,MAAM,OAAO,IAAI;AAC1B;AAEO,SAAS,UAAU,MAAc,MAA+B;AACrE,SAAO,MAAM,UAAU,IAAI;AAC7B;AAEA,SAAS,OAAO,MAAc,IAAsB,MAA+B;AACjF,QAAM,OAAO;AACb,QAAM,MAAM,KAAK,OAAOD,MAAK,MAAM,mBAAmB;AACtD,QAAM,UAAU,QAAQ,KAAK,IAAI;AACjC,QAAM,UAAUA,MAAK,KAAK,uBAAuB;AAEjD,QAAM,MAAM,KAAK,MAAME,cAAa,SAAS,MAAM,CAAC;AACpD,QAAM,OAAO,YAAY,MAAM,IAAI;AACnC,QAAM,gBAAgB,CAAC,GAAI,sBAAsB,MAAM,GAAG,EAAE,aAAa,CAAC,CAAE;AAE5E,MAAI,SAAS,WAAW;AACtB,UAAM,OAAO,IAAI,IAAI,aAAa;AAClC,QAAI,OAAO,OAAO;AAChB,WAAK,IAAI,IAAI;AAAA,IACf,OAAO;AACL,UAAI,CAAC,KAAK,IAAI,IAAI,EAAG,OAAM,IAAI,MAAM,YAAY,IAAI,uCAAuC;AAC5F,UAAI,KAAK,SAAS,EAAG,OAAM,IAAI,MAAM,gEAA2D;AAChG,WAAK,OAAO,IAAI;AAAA,IAClB;AACA,QAAI,YAAY,CAAC,GAAG,IAAI;AAAA,EAC1B,WAAW,OAAO,OAAO;AACvB,QAAI,IAAI,IAAI;AAAA,EACd,OAAO;AAEL,QAAI,IAAI,IAAI,MAAM,KAAM,OAAM,IAAI,MAAM,IAAI,IAAI,uBAAuB,IAAI,6BAA6B;AACxG,QAAI,IAAI,IAAI;AAAA,EACd;AAEA,QAAM,SAAS,sBAAsB,MAAM,GAAG;AAC9C,EAAAC,eAAc,SAAS,KAAK,UAAU,KAAK,MAAM,CAAC,IAAI,IAAI;AAE1D,QAAM,YAAY,UAAU,MAAM,KAAK,QAAQ,eAAe,OAAO;AACrE,UAAQ;AAAA,IACN,GAAG,OAAO,QAAQ,UAAU,SAAS,IAAI,IAAI,KAAK,IAAI,QAAQC,UAAS,QAAQ,IAAI,GAAG,GAAG,KAAK,GAAG;AAAA,EACnG;AACA,MAAI,WAAW;AACb,YAAQ;AAAA,MACN;AAAA,EAAK,SAAS;AAAA,IAChB;AACA,YAAQ,WAAW;AAAA,EACrB;AACF;AAEA,SAAS,UACP,MACA,KACA,QACA,eACA,SACQ;AACR,QAAM,eAAeJ,MAAK,KAAK,OAAO,uBAAuB;AAC7D,QAAM,WAAW,KAAK,MAAME,cAAa,cAAc,MAAM,CAAC;AAE9D,QAAM,EAAE,QAAQ,SAAS,IAAI,aAAa,MAAM,MAAM;AACtD,QAAM,cAAc,IAAI,IAAI,QAAQ;AACpC,QAAM,YAAY,OAAO,KAAK,SAAS,MAAM;AAG7C,QAAM,eAAe,oBAAI,IAA2B;AACpD,aAAW,KAAK,oBAAI,IAAI,CAAC,GAAG,eAAe,GAAI,OAAO,aAAa,CAAC,CAAE,CAAC;AACrE,iBAAa,IAAI,GAAG,iBAAiB,MAAM,CAAC,CAAC;AAG/C,aAAW,KAAK,WAAW;AACzB,QAAI,YAAY,IAAI,CAAC,EAAG;AACxB,IAAAG,QAAOL,MAAK,KAAK,OAAO,UAAU,CAAC,GAAG,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AACtE,IAAAK,QAAOL,MAAK,KAAK,OAAO,SAAS,CAAC,GAAG,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AACrE,WAAO,SAAS,OAAO,CAAC;AACxB,eAAW,OAAO,aAAa,OAAO;AACpC,UAAI,IAAK,CAAAK,QAAOL,MAAK,KAAK,KAAK,CAAC,GAAG,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAAA,EACvE;AAGA,MAAI,YAAY;AAChB,aAAW,KAAK,UAAU;AACxB,UAAM,IAAI,eAAe,MAAM,KAAK,QAAQ,CAAC;AAC7C,aAAS,OAAO,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,QAAQ,EAAE,OAAO;AAC1D,iBAAa,EAAE;AAAA,EACjB;AAGA,aAAW,KAAK,eAAe;AAC7B,SAAK,OAAO,aAAa,CAAC,GAAG,SAAS,CAAC,EAAG;AAC1C,UAAM,MAAM,aAAa,IAAI,CAAC;AAC9B,QAAI,OAAOD,YAAWC,MAAK,KAAK,GAAG,CAAC,EAAG,CAAAK,QAAOL,MAAK,KAAK,GAAG,GAAG,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAAA,EAChG;AACA,gBAAc,MAAM,KAAK,QAAQ,UAAU,OAAO;AAElD,gBAAc,KAAK,QAAQ,SAAS,MAAM;AAC1C,SAAO;AACT;;;ATxHA,IAAM,EAAE,QAAQ,IAAI,KAAK,MAAMM,cAAa,IAAI,IAAI,sBAAsB,YAAY,GAAG,GAAG,MAAM,CAAC;AAInG,IAAM,UAAU,IAAI,QAAQ;AAE5B,QACG,KAAK,KAAK,EACV,YAAY,kFAAkF,EAC9F,QAAQ,OAAO;AAElB,QACG,QAAQ,MAAM,EACd,YAAY,0EAA0E,EACtF,OAAO,mBAAmB,iEAAiE,EAC3F,OAAO,eAAe,kCAAkC,EACxD,OAAO,UAAU,8DAA8D,EAC/E,OAAO,qBAAqB,4CAA4C,EACxE,OAAO,CAAC,SAAS,QAAQ,IAAI,CAAC;AAEjC,QACG,QAAQ,QAAQ,EAChB,YAAY,kEAAkE,EAC9E,eAAe,kBAAkB,oBAAoB,EACrD,OAAO,mBAAmB,iEAAiE,EAC3F,OAAO,eAAe,yEAAyE,EAC/F,OAAO,CAAC,SAAS,UAAU,IAAI,CAAC;AAEnC,QACG,QAAQ,MAAM,EACd,YAAY,+EAA+E,EAC3F,OAAO,eAAe,4BAA4B,EAClD,OAAO,CAAC,SAAS,QAAQ,IAAI,CAAC;AAEjC,QACG,QAAQ,KAAK,EACb,SAAS,aAAa,8DAA8D,EACpF,YAAY,+EAA+E,EAC3F,OAAO,eAAe,8BAA8B,EACpD,OAAO,UAAU,8DAA8D,EAC/E,OAAO,CAAC,SAAS,SAAS,OAAO,SAAS,IAAI,CAAC;AAElD,QACG,QAAQ,QAAQ,EAChB,SAAS,aAAa,gEAAgE,EACtF,YAAY,gEAAgE,EAC5E,OAAO,eAAe,8BAA8B,EACpD,OAAO,UAAU,8DAA8D,EAC/E,OAAO,CAAC,SAAS,SAAS,UAAU,SAAS,IAAI,CAAC;AAErD,QACG,QAAQ,KAAK,EACb,YAAY,4FAAuF,EACnG,OAAO,MAAM,OAAO,CAAC;AAExB,QAAQ,WAAW,QAAQ,IAAI,EAAE,MAAM,CAAC,QAAiB;AACvD,MAAI,eAAe,UAAU;AAC3B,YAAQ,MAAM,wBAAwB;AACtC,eAAW,SAAS,IAAI,OAAQ,SAAQ,MAAM,OAAO,MAAM,KAAK,KAAK,GAAG,KAAK,QAAQ,KAAK,MAAM,OAAO,EAAE;AAAA,EAC3G,OAAO;AACL,YAAQ,MAAM,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,EAChE;AACA,UAAQ,KAAK,CAAC;AAChB,CAAC;","names":["readFileSync","readFileSync","writeFileSync","join","join","p","join","existsSync","join","readFileSync","join","writeFileSync","readFileSync","writeFileSync","existsSync","join","relative","readFileSync","writeFileSync","existsSync","join","join","existsSync","readFileSync","writeFileSync","join","readFileSync","writeFileSync","relative","existsSync","readFileSync","readdirSync","existsSync","mkdirSync","rmSync","symlinkSync","join","relative","join","existsSync","readdirSync","readFileSync","mkdirSync","relative","rmSync","symlinkSync","readFileSync","writeFileSync","mkdirSync","join","relative","readFileSync","join","mkdirSync","writeFileSync","relative","readFileSync","writeFileSync","existsSync","rmSync","join","relative","existsSync","join","p","readFileSync","writeFileSync","relative","rmSync","readFileSync"]}
|
|
1
|
+
{"version":3,"sources":["../../src/cli/index.ts","../../src/cli/commands/init.ts","../../src/cli/root.ts","../../src/cli/consumer-io.ts","../../src/cli/wizard.ts","../../src/cli/commands/sync.ts","../../src/cli/reconcile.ts","../../src/cli/commands/dev.ts","../../src/cli/commands/render.ts","../../src/cli/commands/adapter.ts"],"sourcesContent":["#!/usr/bin/env node\n// aef — CLI for the Agentic Engineering Framework.\n//\n// aef init [--config <cfg>] [--out <dir>] [--copy] [--interactive]\n// aef sync [--out <dir>]\n// aef add <adapter> [--out <dir>] [--copy]\n// aef remove <adapter> [--out <dir>] [--copy]\n// aef dev\nimport { readFileSync } from 'node:fs'\nimport { Command } from 'commander'\nimport { ZodError, ZodIssueCode } from 'zod'\nimport { runInit } from './commands/init.js'\nimport { runSync } from './commands/sync.js'\nimport { runDev } from './commands/dev.js'\nimport { runRender } from './commands/render.js'\nimport { runAdd, runRemove } from './commands/adapter.js'\nimport { FrameworkConfigSchema } from '../core/contracts.js'\n\n// Single source of truth for the version: read the package's own package.json at\n// runtime so it never drifts from release-please's bump (dev: src/cli/, built:\n// dist/cli/ — both resolve to the package root).\nconst { version } = JSON.parse(readFileSync(new URL('../../package.json', import.meta.url), 'utf8')) as {\n version: string\n}\n\nfunction levenshtein(a: string, b: string): number {\n const dp = Array.from({ length: b.length + 1 }, (_, j) => j)\n for (let i = 1; i <= a.length; i++) {\n let prev = dp[0]!\n dp[0] = i\n for (let j = 1; j <= b.length; j++) {\n const temp = dp[j]!\n dp[j] = a[i - 1] === b[j - 1] ? prev : 1 + Math.min(prev, temp, dp[j - 1]!)\n prev = temp\n }\n }\n return dp[b.length]!\n}\n\nfunction suggestKey(unknown: string, valid: string[]): string | null {\n let best: string | null = null\n let bestDist = Infinity\n for (const k of valid) {\n const d = levenshtein(unknown, k)\n if (d < bestDist) {\n bestDist = d\n best = k\n }\n }\n return bestDist / Math.max(unknown.length, best!.length) <= 0.4 ? best : null\n}\n\nconst program = new Command()\n\nprogram\n .name('aef')\n .description('Render slot-based engineering skills into a consumer repo and keep them in sync.')\n .version(version)\n\nprogram\n .command('init')\n .description('Render the configured skill set into a consumer repo and wire harnesses.')\n .option('--config <path>', 'path to framework.config.json (required unless --interactive)')\n .option('--out <dir>', 'consumer directory to write into')\n .option('--copy', 'copy rendered skills into harness dirs instead of symlinking')\n .option('-i, --interactive', 'build the config interactively via prompts')\n .action((opts) => runInit(opts))\n\nprogram\n .command('render')\n .description('Render a single skill to stdout (or --out <dir>) for inspection.')\n .requiredOption('--skill <name>', 'skill id to render')\n .option('--config <path>', 'path to framework.config.json (required)')\n .option('--out <dir>', 'write SKILL.md + provenance.json under <dir>/<skill>/ instead of stdout')\n .action((opts) => runRender(opts))\n\nprogram\n .command('sync')\n .description('Re-render from framework source and reconcile with local edits (3-way merge).')\n .option('--out <dir>', 'consumer directory to sync')\n .action((opts) => runSync(opts))\n\nprogram\n .command('add')\n .argument('<adapter>', 'adapter name to select (axis inferred from its adapter.json)')\n .description('Select an adapter and reconcile the installed skill set (merges local edits).')\n .option('--out <dir>', 'consumer directory to update')\n .option('--copy', 'copy rendered skills into harness dirs instead of symlinking')\n .action((adapter, opts) => runAdd(adapter, opts))\n\nprogram\n .command('remove')\n .argument('<adapter>', 'adapter name to deselect (axis inferred from its adapter.json)')\n .description('Deselect an adapter; uninstalls skills that required its axis.')\n .option('--out <dir>', 'consumer directory to update')\n .option('--copy', 'copy rendered skills into harness dirs instead of symlinking')\n .action((adapter, opts) => runRemove(adapter, opts))\n\nprogram\n .command('dev')\n .description('Meta-install: wire this repo’s harness dirs to dev/ skills for framework development.')\n .action(() => runDev())\n\nconst validRootKeys = Object.keys(FrameworkConfigSchema.shape)\n\nprogram.parseAsync(process.argv).catch((err: unknown) => {\n if (err instanceof ZodError) {\n console.error('Invalid configuration:')\n for (const issue of err.issues) {\n if (issue.code === ZodIssueCode.unrecognized_keys && issue.path.length === 0) {\n for (const key of issue.keys) {\n const suggestion = suggestKey(key, validRootKeys)\n const hint = suggestion != null ? ` Did you mean '${suggestion}'?` : ''\n console.error(` - Unknown key '${key}'.${hint}`)\n }\n console.error(` Valid keys: ${validRootKeys.join(', ')}`)\n } else {\n console.error(` - ${issue.path.join('.') || '(root)'}: ${issue.message}`)\n }\n }\n } else {\n console.error(err instanceof Error ? err.message : String(err))\n }\n process.exit(1)\n})\n","// `aef init` — render the configured skill set into <out>/.ai/skills/, snapshot a\n// BASE under <out>/.ai/.base/, write the render manifest (sync's base), persist the\n// resolved config, and wire each harness.\nimport { readFileSync, writeFileSync } from 'node:fs'\nimport { join, relative } from 'node:path'\nimport { FrameworkConfigSchema } from '../../core/contracts.js'\nimport { renderSkill } from '../../core/render.js'\nimport { selectSkills } from '../../core/select.js'\nimport { FRAMEWORK_ROOT } from '../root.js'\nimport {\n writeSkill,\n writeBase,\n writeManifest,\n wireHarnesses,\n writeConventions,\n type ManifestSkills,\n} from '../consumer-io.js'\nimport { runWizard } from '../wizard.js'\n\nexport interface InitOptions {\n config?: string\n out?: string\n copy?: boolean\n interactive?: boolean\n}\n\nexport async function runInit(opts: InitOptions): Promise<void> {\n const root = FRAMEWORK_ROOT\n\n if (opts.config && opts.interactive) {\n throw new Error(\n `--config and --interactive are mutually exclusive. Pass --config to use a file or --interactive to build one via prompts.`,\n )\n }\n if (!opts.config && !opts.interactive) {\n throw new Error(\n `--config is required.\\n\\nUsage: aef init --config framework.config.json --out . --copy\\n\\nTo get started, create a framework.config.json. Minimum required:\\n {\\n \"harnesses\": [\"claude-code\"]\\n }\\n\\nRun 'aef init --help' for all options.`,\n )\n }\n\n // `raw` is what we persist to framework.config.json (byte-stable); `config` is the\n // zod-validated view the renderer consumes.\n const raw: unknown = opts.interactive\n ? await runWizard(root)\n : JSON.parse(readFileSync(opts.config!, 'utf8'))\n const config = FrameworkConfigSchema.parse(raw)\n\n const out = opts.out ?? join(root, 'examples/consumer')\n const useCopy = Boolean(opts.copy)\n\n const { skills, skipped } = selectSkills(root, config)\n\n const manifestSkills: ManifestSkills = {}\n for (const skill of skills) {\n const { rendered, manifest, digest } = renderSkill(root, config, skill)\n writeSkill(out, skill, rendered, manifest)\n writeBase(out, skill, rendered)\n manifestSkills[skill] = { digest, inputs: manifest.inputs }\n }\n writeManifest(out, config, manifestSkills)\n writeFileSync(join(out, 'framework.config.json'), JSON.stringify(raw, null, 2) + '\\n')\n\n const conventions = writeConventions(root, out, config)\n const wired = wireHarnesses(root, out, config, skills, useCopy)\n\n console.log(`Initialised agentic framework into ${relative(process.cwd(), out) || '.'}`)\n console.log(` skills installed: ${skills.join(', ') || '(none)'}`)\n console.log(` conventions: ${conventions.join(', ')}`)\n if (skipped.length) console.log(` skipped (axis not configured): ${skipped.join(', ')}`)\n console.log(` harnesses wired: ${wired.join(' | ') || '(none)'}`)\n}\n","import { fileURLToPath } from 'node:url'\nimport { dirname, join } from 'node:path'\n\n// The framework SOURCE root (where core/, adapters/, schemas/ live). Resolves the\n// same whether running from src/cli/ via tsx or from dist/cli/ after a build —\n// both are two levels below the package root.\nexport const FRAMEWORK_ROOT = join(dirname(fileURLToPath(import.meta.url)), '..', '..')\n","// Filesystem side of init/sync: writing a consumer's .ai/ tree and wiring harnesses.\n// Kept separate from the command wiring so the behaviour is unit-testable.\nimport {\n readFileSync,\n writeFileSync,\n mkdirSync,\n existsSync,\n lstatSync,\n rmSync,\n cpSync,\n symlinkSync,\n} from 'node:fs'\nimport { join } from 'node:path'\nimport { AdapterSchema, type FrameworkConfig } from '../core/contracts.js'\nimport type { InputRef, RenderManifest } from '../core/render.js'\n\nexport const isLink = (p: string): boolean => {\n try {\n return lstatSync(p).isSymbolicLink()\n } catch {\n return false\n }\n}\n\nexport function pick<T extends Record<string, unknown>>(o: T, keys: string[]): Record<string, unknown> {\n const r: Record<string, unknown> = {}\n for (const k of keys) if (k in o) r[k] = o[k]\n return r\n}\n\n/**\n * Install the generic `core/ai` conventions into a consumer: the specs/qa/runs scaffolding,\n * a starter lessons.md, a CLAUDE.md, and AGENTS.md rendered from the template with\n * {{PROJECT_NAME}} substituted. Idempotent — safe to re-run. Returns the paths written.\n */\nexport function writeConventions(root: string, out: string, config: FrameworkConfig): string[] {\n const projectName = config.projectName ?? 'your project'\n const sub = (s: string): string => s.split('{{PROJECT_NAME}}').join(projectName)\n const ai = join(out, '.ai')\n mkdirSync(ai, { recursive: true })\n const written: string[] = []\n\n for (const dir of ['specs', 'qa', 'runs']) {\n const src = join(root, 'core', 'ai', dir)\n if (existsSync(src)) {\n cpSync(src, join(ai, dir), { recursive: true })\n written.push(`.ai/${dir}/`)\n }\n }\n // Substitute {{PROJECT_NAME}} in the one convention file that carries it.\n const specsReadme = join(ai, 'specs', 'README.md')\n if (existsSync(specsReadme)) writeFileSync(specsReadme, sub(readFileSync(specsReadme, 'utf8')))\n\n const lessonsSrc = join(root, 'core', 'ai', 'lessons.md')\n if (existsSync(lessonsSrc)) {\n writeFileSync(join(ai, 'lessons.md'), sub(readFileSync(lessonsSrc, 'utf8')))\n written.push('.ai/lessons.md')\n }\n // Synced-read-only generic lessons.\n const fwLessons = join(root, 'core', 'ai', 'lessons.framework.md')\n if (existsSync(fwLessons)) {\n writeFileSync(join(ai, 'lessons.framework.md'), readFileSync(fwLessons, 'utf8'))\n written.push('.ai/lessons.framework.md')\n }\n // Framework-feedback outbox: only for consumers who have opted in to the framework tier.\n const outbox = join(root, 'core', 'ai', 'framework-feedback')\n if (existsSync(outbox) && config.tiers?.includes('framework')) {\n cpSync(outbox, join(ai, 'framework-feedback'), { recursive: true })\n written.push('.ai/framework-feedback/')\n }\n\n const tpl = join(root, 'core', 'AGENTS.md.template')\n if (existsSync(tpl)) {\n writeFileSync(join(out, 'AGENTS.md'), sub(readFileSync(tpl, 'utf8')))\n written.push('AGENTS.md')\n }\n writeFileSync(join(out, 'CLAUDE.md'), '@AGENTS.md\\n')\n written.push('CLAUDE.md')\n return written\n}\n\nexport function writeSkill(out: string, skill: string, rendered: string, manifest: RenderManifest): void {\n const dest = join(out, '.ai', 'skills', skill)\n mkdirSync(dest, { recursive: true })\n writeFileSync(join(dest, 'SKILL.md'), rendered)\n writeFileSync(join(dest, 'provenance.json'), JSON.stringify(manifest, null, 2) + '\\n')\n}\n\nexport function writeBase(out: string, skill: string, rendered: string): void {\n const d = join(out, '.ai', '.base', skill)\n mkdirSync(d, { recursive: true })\n writeFileSync(join(d, 'SKILL.md'), rendered)\n}\n\nexport type ManifestSkills = Record<string, { digest: string; inputs: InputRef[] }>\n\nexport function writeManifest(out: string, config: FrameworkConfig, skills: ManifestSkills): void {\n mkdirSync(join(out, '.ai'), { recursive: true })\n writeFileSync(\n join(out, '.ai', '.render-manifest.json'),\n JSON.stringify(\n { selection: pick(config, ['orm', 'ui', 'stack', 'harnesses', 'tiers']), skills },\n null,\n 2,\n ) + '\\n',\n )\n}\n\nexport function harnessSkillsDir(root: string, harness: string): string | null {\n const p = join(root, 'adapters', 'harness', harness, 'adapter.json')\n if (!existsSync(p)) return null\n const ad = AdapterSchema.parse(JSON.parse(readFileSync(p, 'utf8')))\n return ad.skillsDir ?? null\n}\n\nexport function wireNewSkills(root: string, out: string, config: FrameworkConfig, skills: string[]): void {\n for (const harness of config.harnesses) {\n const adPath = join(root, 'adapters', 'harness', harness, 'adapter.json')\n if (!existsSync(adPath)) continue\n const ad = AdapterSchema.parse(JSON.parse(readFileSync(adPath, 'utf8')))\n if (!ad.skillsDir || !ad.linkBase) continue\n const hdir = join(out, ad.skillsDir)\n mkdirSync(hdir, { recursive: true })\n for (const skill of skills) {\n const link = join(hdir, skill)\n if (!existsSync(link) && !isLink(link)) symlinkSync(`${ad.linkBase}/${skill}`, link)\n }\n }\n}\n\nexport function wireHarnesses(\n root: string,\n out: string,\n config: FrameworkConfig,\n skills: string[],\n useCopy: boolean,\n): string[] {\n const aiSkills = join(out, '.ai', 'skills')\n const wired: string[] = []\n for (const harness of config.harnesses) {\n const adPath = join(root, 'adapters', 'harness', harness, 'adapter.json')\n if (!existsSync(adPath)) {\n console.warn(`! no harness adapter '${harness}', skipping`)\n continue\n }\n const ad = AdapterSchema.parse(JSON.parse(readFileSync(adPath, 'utf8')))\n if (!ad.skillsDir || !ad.linkBase) {\n console.warn(`! harness adapter '${harness}' is missing skillsDir/linkBase, skipping`)\n continue\n }\n const hdir = join(out, ad.skillsDir)\n mkdirSync(hdir, { recursive: true })\n for (const skill of skills) {\n const link = join(hdir, skill)\n if (existsSync(link) || isLink(link)) rmSync(link, { recursive: true, force: true })\n if (useCopy) cpSync(join(aiSkills, skill), link, { recursive: true })\n else symlinkSync(`${ad.linkBase}/${skill}`, link)\n }\n wired.push(`${harness} -> ${ad.skillsDir} (${useCopy ? 'copy' : 'symlink'})`)\n }\n return wired\n}\n","// Interactive `init` wizard (opt-in via --interactive). Discovers the available\n// adapters on disk and builds a framework.config object via @clack/prompts.\nimport { readdirSync, existsSync } from 'node:fs'\nimport { join } from 'node:path'\nimport * as p from '@clack/prompts'\n\nfunction listAdapters(root: string, axis: string): string[] {\n const dir = join(root, 'adapters', axis)\n if (!existsSync(dir)) return []\n return readdirSync(dir).filter((n) => existsSync(join(dir, n, 'adapter.json')))\n}\n\nfunction bail<T>(value: T | symbol): T {\n if (p.isCancel(value)) {\n p.cancel('Cancelled — nothing written.')\n process.exit(1)\n }\n return value as T\n}\n\nconst axisOptions = (root: string, axis: string): { value: string | null; label: string }[] => [\n { value: null, label: 'none' },\n ...listAdapters(root, axis).map((v) => ({ value: v, label: v })),\n]\n\nexport async function runWizard(root: string): Promise<Record<string, unknown>> {\n p.intro('aef init')\n\n const projectName = bail(\n await p.text({ message: 'Project name', placeholder: 'my-app', defaultValue: 'my-app' }),\n )\n const harnesses = bail(\n await p.multiselect({\n message: 'Which AI harnesses should be wired?',\n options: listAdapters(root, 'harness').map((v) => ({ value: v, label: v })),\n required: true,\n }),\n )\n const orm = bail(\n await p.select({ message: 'ORM adapter', options: axisOptions(root, 'orm'), initialValue: null }),\n )\n const ui = bail(\n await p.select({ message: 'UI adapter', options: axisOptions(root, 'ui'), initialValue: null }),\n )\n\n p.outro('Configuration ready.')\n\n return {\n $schema: './schemas/framework.config.schema.json',\n projectName,\n harnesses,\n orm,\n ui,\n }\n}\n","// `aef sync` — re-render from the (updated) framework source and reconcile with\n// local edits via a git-native 3-way merge (BASE = last render, LOCAL = on-disk,\n// NEW = fresh render). Exit code 2 signals unresolved conflicts written to the tree.\nimport { readFileSync, writeFileSync, existsSync, rmSync } from 'node:fs'\nimport { join, relative } from 'node:path'\nimport { FrameworkConfigSchema } from '../../core/contracts.js'\nimport { selectSkills } from '../../core/select.js'\nimport { FRAMEWORK_ROOT } from '../root.js'\nimport { reconcileSkill, type ReconcileStatus } from '../reconcile.js'\nimport { writeManifest, wireNewSkills, harnessSkillsDir, type ManifestSkills } from '../consumer-io.js'\n\ninterface RenderManifestFile {\n selection: unknown\n skills: ManifestSkills\n}\n\nconst REPORT: Record<ReconcileStatus, (s: string) => string> = {\n installed: (s) => ` + ${s}: installed`,\n unchanged: (s) => ` = ${s}: framework unchanged`,\n forwarded: (s) => ` ↑ ${s}: updated (no local edits)`,\n merged: (s) => ` ⇄ ${s}: merged local edits + framework update (clean)`,\n conflict: (s) => ` ⇄ ${s}: merged — CONFLICT(S), resolve in working tree`,\n}\n\nexport interface SyncOptions {\n out?: string\n}\n\nexport function runSync(opts: SyncOptions): void {\n const root = FRAMEWORK_ROOT\n const out = opts.out ?? join(root, 'examples/consumer')\n const config = FrameworkConfigSchema.parse(\n JSON.parse(readFileSync(join(out, 'framework.config.json'), 'utf8')),\n )\n const manifestPath = join(out, '.ai', '.render-manifest.json')\n const manifest = JSON.parse(readFileSync(manifestPath, 'utf8')) as RenderManifestFile\n\n const { skills: desired } = selectSkills(root, config)\n const desiredSet = new Set(desired)\n const installed = Object.keys(manifest.skills)\n\n const harnessDirs = new Map<string, string | null>()\n for (const h of config.harnesses) harnessDirs.set(h, harnessSkillsDir(root, h))\n\n // Remove skills no longer in the desired set (tier removed or axis cleared).\n for (const s of installed) {\n if (desiredSet.has(s)) continue\n rmSync(join(out, '.ai', 'skills', s), { recursive: true, force: true })\n rmSync(join(out, '.ai', '.base', s), { recursive: true, force: true })\n delete manifest.skills[s]\n for (const dir of harnessDirs.values())\n if (dir) rmSync(join(out, dir, s), { recursive: true, force: true })\n }\n\n const report: string[] = []\n let conflicts = 0\n const newSkills: string[] = []\n for (const skill of desired) {\n const isNew = !manifest.skills[skill]\n const r = reconcileSkill(root, out, config, skill)\n manifest.skills[skill] = { digest: r.digest, inputs: r.inputs }\n conflicts += r.conflicts\n report.push(REPORT[r.status](skill))\n if (isNew) newSkills.push(skill)\n }\n\n if (newSkills.length > 0) wireNewSkills(root, out, config, newSkills)\n\n writeManifest(out, config, manifest.skills)\n\n console.log(`Synced ${relative(process.cwd(), out) || '.'} from framework source`)\n // Refresh synced read-only framework lessons (loop closure, decision #8).\n const fwLessonsSrc = join(root, 'core', 'ai', 'lessons.framework.md')\n if (existsSync(fwLessonsSrc)) {\n const dest = join(out, '.ai', 'lessons.framework.md')\n const next = readFileSync(fwLessonsSrc, 'utf8')\n if (!existsSync(dest) || readFileSync(dest, 'utf8') !== next) {\n writeFileSync(dest, next)\n report.push(' ↑ lessons.framework.md: refreshed (synced, read-only)')\n }\n }\n\n report.forEach((l) => console.log(l))\n if (conflicts) {\n console.log(\n `\\n${conflicts} conflict(s) written as <<<<<<< markers. Review with 'git diff', resolve, commit.`,\n )\n process.exitCode = 2\n }\n}\n","// Shared per-skill reconcile: render a skill from the current framework source and\n// fold the result into a consumer, preserving local edits via a git-native 3-way merge.\n// Used by both `aef sync` and `aef add`/`remove` so the reconcile semantics —\n// fast-forward, clean merge, conflict, and provenance refresh — live in exactly one place.\nimport { readFileSync, writeFileSync, existsSync } from 'node:fs'\nimport { join } from 'node:path'\nimport { renderSkill, type InputRef } from '../core/render.js'\nimport { mergeFile } from '../core/merge.js'\nimport type { FrameworkConfig } from '../core/contracts.js'\nimport { writeSkill, writeBase } from './consumer-io.js'\n\nexport type ReconcileStatus = 'installed' | 'unchanged' | 'forwarded' | 'merged' | 'conflict'\n\nexport interface ReconcileResult {\n status: ReconcileStatus\n digest: string\n inputs: InputRef[]\n conflicts: number\n}\n\n/**\n * Reconcile one skill in `out` against the current render:\n * - not yet on disk → install fresh (+ BASE),\n * - framework unchanged → leave LOCAL alone (local edits kept),\n * - framework changed, no edits → fast-forward to NEW,\n * - both changed → 3-way merge (conflicts land as <<<<<<< markers).\n * Always refreshes provenance.json to the fresh render and returns the new digest/inputs\n * so the caller can update the render manifest.\n */\nexport function reconcileSkill(\n root: string,\n out: string,\n config: FrameworkConfig,\n skill: string,\n): ReconcileResult {\n const { rendered: NEW, manifest, digest } = renderSkill(root, config, skill)\n const skillMd = join(out, '.ai', 'skills', skill, 'SKILL.md')\n\n if (!existsSync(skillMd)) {\n writeSkill(out, skill, NEW, manifest)\n writeBase(out, skill, NEW)\n return { status: 'installed', digest, inputs: manifest.inputs, conflicts: 0 }\n }\n\n const baseMd = join(out, '.ai', '.base', skill, 'SKILL.md')\n const BASE = existsSync(baseMd) ? readFileSync(baseMd, 'utf8') : NEW\n const LOCAL = readFileSync(skillMd, 'utf8')\n\n let status: ReconcileStatus = 'unchanged'\n let conflicts = 0\n if (NEW !== BASE) {\n if (LOCAL === BASE) {\n writeFileSync(skillMd, NEW)\n status = 'forwarded'\n } else {\n const { merged, conflicts: n } = mergeFile(LOCAL, BASE, NEW)\n writeFileSync(skillMd, merged)\n conflicts = n\n status = n ? 'conflict' : 'merged'\n }\n writeBase(out, skill, NEW)\n }\n // Provenance always tracks the fresh render (improve-framework reads it to route edits).\n writeFileSync(\n join(out, '.ai', 'skills', skill, 'provenance.json'),\n JSON.stringify(manifest, null, 2) + '\\n',\n )\n return { status, digest, inputs: manifest.inputs, conflicts }\n}\n","// `aef dev` — the \"meta\" install for developing THIS framework. Wires the repo's\n// own harness skill dirs to dev/ skills (source symlinks). Installs the toolchain, not\n// the shipped product; harness dirs are gitignored.\nimport { readFileSync, readdirSync, existsSync, mkdirSync, rmSync, symlinkSync } from 'node:fs'\nimport { join, relative } from 'node:path'\nimport { AdapterSchema } from '../../core/contracts.js'\nimport { FRAMEWORK_ROOT } from '../root.js'\nimport { isLink } from '../consumer-io.js'\n\nexport function runDev(): void {\n const root = FRAMEWORK_ROOT\n const devSkillsDir = join(root, 'dev', 'skills')\n if (!existsSync(devSkillsDir)) {\n console.error('no dev/skills/ found')\n process.exit(1)\n }\n const devSkills = readdirSync(devSkillsDir).filter((d) => existsSync(join(devSkillsDir, d, 'SKILL.md')))\n const harnessRoot = join(root, 'adapters', 'harness')\n const harnesses = readdirSync(harnessRoot).filter((d) => existsSync(join(harnessRoot, d, 'adapter.json')))\n\n const wired: string[] = []\n for (const harness of harnesses) {\n const ad = AdapterSchema.parse(\n JSON.parse(readFileSync(join(harnessRoot, harness, 'adapter.json'), 'utf8')),\n )\n if (!ad.skillsDir) continue\n const hdir = join(root, ad.skillsDir)\n mkdirSync(hdir, { recursive: true })\n const target = relative(hdir, devSkillsDir) // robust relative link target\n for (const skill of devSkills) {\n const link = join(hdir, skill)\n if (existsSync(link) || isLink(link)) rmSync(link, { recursive: true, force: true })\n symlinkSync(join(target, skill), link)\n }\n wired.push(`${harness} -> ${ad.skillsDir}`)\n }\n console.log('Framework dev install (meta):')\n console.log(` dev skills: ${devSkills.join(', ') || '(none)'}`)\n console.log(` harnesses : ${wired.join(' | ')}`)\n console.log(' (harness dirs are gitignored; re-run after adding a dev skill)')\n}\n","// `aef render` — render a single skill to stdout (or --out dir) for inspection.\n// The lightweight counterpart to `init`; handy while authoring skills/adapters and\n// the render step the improve-framework skill points at.\nimport { readFileSync, writeFileSync, mkdirSync } from 'node:fs'\nimport { join, relative } from 'node:path'\nimport { FrameworkConfigSchema } from '../../core/contracts.js'\nimport { renderSkill } from '../../core/render.js'\nimport { FRAMEWORK_ROOT } from '../root.js'\n\nexport interface RenderOptions {\n skill: string\n config?: string\n out?: string\n}\n\nexport function runRender(opts: RenderOptions): void {\n if (!opts.config) {\n throw new Error(\n `--config is required.\\n\\nUsage: aef render --skill <name> --config framework.config.json\\n\\nRun 'aef render --help' for all options.`,\n )\n }\n const root = FRAMEWORK_ROOT\n const config = FrameworkConfigSchema.parse(JSON.parse(readFileSync(opts.config, 'utf8')))\n const { rendered, manifest, digest } = renderSkill(root, config, opts.skill)\n\n if (opts.out) {\n const dest = join(opts.out, opts.skill)\n mkdirSync(dest, { recursive: true })\n writeFileSync(join(dest, 'SKILL.md'), rendered)\n writeFileSync(join(dest, 'provenance.json'), JSON.stringify(manifest, null, 2) + '\\n')\n console.error(\n `Rendered '${opts.skill}' (orm=${manifest.selection.orm ?? 'none'}) -> ${relative(root, dest)}`,\n )\n console.error(\n ` digest ${digest} · ${manifest.regions.length} regions · ${manifest.inputs.length} inputs`,\n )\n } else {\n // Body to stdout (pipeable); summary to stderr.\n process.stdout.write(rendered)\n console.error(\n ` digest ${digest} · ${manifest.regions.length} regions · ${manifest.inputs.length} inputs`,\n )\n }\n}\n","// `aef add <adapter>` / `aef remove <adapter>` — change an axis selection in a\n// consumer's framework.config.json and reconcile the installed skill set:\n// • newly-selected skills are rendered fresh (+ BASE snapshot),\n// • skills no longer selected are uninstalled (skill dir, BASE, harness links),\n// • surviving skills are 3-way merged (like sync) so adapter-content changes flow in\n// without clobbering local edits.\n// The adapter's axis is read from its adapter.json, so the command is `add <name>`.\nimport { readFileSync, writeFileSync, existsSync, rmSync, cpSync } from 'node:fs'\nimport { join, relative } from 'node:path'\nimport { FrameworkConfigSchema, type FrameworkConfig } from '../../core/contracts.js'\nimport { selectSkills, loadTiers } from '../../core/select.js'\nimport { FRAMEWORK_ROOT } from '../root.js'\nimport { writeManifest, wireHarnesses, harnessSkillsDir, type ManifestSkills } from '../consumer-io.js'\nimport { reconcileSkill } from '../reconcile.js'\n\nconst AXES = ['orm', 'ui', 'stack', 'harness'] as const\n\ninterface ManifestFile {\n selection: unknown\n skills: ManifestSkills\n}\n\nexport interface AdapterCmdOptions {\n out?: string\n copy?: boolean\n}\n\n/** Find which axis an adapter name belongs to by locating its adapter.json on disk. */\nfunction resolveAxis(root: string, name: string): (typeof AXES)[number] {\n for (const axis of AXES) {\n if (existsSync(join(root, 'adapters', axis, name, 'adapter.json'))) return axis\n }\n throw new Error(`no adapter '${name}' found under adapters/{${AXES.join(',')}}/`)\n}\n\nexport function runAdd(name: string, opts: AdapterCmdOptions): void {\n mutate(name, 'add', opts)\n}\n\nexport function runRemove(name: string, opts: AdapterCmdOptions): void {\n mutate(name, 'remove', opts)\n}\n\nfunction mutate(name: string, op: 'add' | 'remove', opts: AdapterCmdOptions): void {\n const root = FRAMEWORK_ROOT\n const out = opts.out ?? join(root, 'examples/consumer')\n const useCopy = Boolean(opts.copy)\n const cfgPath = join(out, 'framework.config.json')\n\n const raw = JSON.parse(readFileSync(cfgPath, 'utf8')) as Record<string, unknown>\n const prevConfig = FrameworkConfigSchema.parse(raw)\n const prevHarnesses = [...(prevConfig.harnesses ?? [])]\n\n const tierDef = loadTiers(root)\n const isTier = name in tierDef.tiers\n\n if (isTier) {\n if (tierDef.default.includes(name))\n throw new Error(\n `tier '${name}' is a default tier — it is always active and cannot be ${op === 'add' ? 'explicitly opted in' : 'removed'}`,\n )\n const current = prevConfig.tiers ?? []\n if (op === 'add') {\n if (!current.includes(name)) raw.tiers = [...current, name]\n } else {\n if (!current.includes(name)) throw new Error(`tier '${name}' is not enabled; nothing to remove`)\n const after = current.filter((t) => t !== name)\n if (after.length > 0) raw.tiers = after\n else delete raw.tiers\n }\n } else {\n const axis = resolveAxis(root, name)\n if (axis === 'harness') {\n const list = new Set(prevHarnesses)\n if (op === 'add') {\n list.add(name)\n } else {\n if (!list.has(name)) throw new Error(`harness '${name}' is not installed; nothing to remove`)\n if (list.size === 1) throw new Error('cannot remove the last harness — at least one is required')\n list.delete(name)\n }\n raw.harnesses = [...list]\n } else if (op === 'add') {\n raw[axis] = name\n } else {\n if (raw[axis] !== name)\n throw new Error(`'${name}' is not the active ${axis} adapter; nothing to remove`)\n raw[axis] = null\n }\n }\n\n const config = FrameworkConfigSchema.parse(raw)\n writeFileSync(cfgPath, JSON.stringify(raw, null, 2) + '\\n')\n\n if (isTier && name === 'framework') {\n const outboxDst = join(out, '.ai', 'framework-feedback')\n if (op === 'add') {\n const outboxSrc = join(root, 'core', 'ai', 'framework-feedback')\n if (existsSync(outboxSrc)) cpSync(outboxSrc, outboxDst, { recursive: true })\n } else {\n rmSync(outboxDst, { recursive: true, force: true })\n }\n }\n\n const conflicts = reconcile(root, out, config, prevHarnesses, useCopy)\n const kind = isTier ? 'tier' : 'adapter'\n console.log(\n `${op === 'add' ? 'Added' : 'Removed'} ${name} (${kind}) in ${relative(process.cwd(), out) || '.'}`,\n )\n if (conflicts) {\n console.log(\n `\\n${conflicts} conflict(s) written as <<<<<<< markers — review with 'git diff', resolve, commit.`,\n )\n process.exitCode = 2\n }\n}\n\nfunction reconcile(\n root: string,\n out: string,\n config: FrameworkConfig,\n prevHarnesses: string[],\n useCopy: boolean,\n): number {\n const manifestPath = join(out, '.ai', '.render-manifest.json')\n const manifest = JSON.parse(readFileSync(manifestPath, 'utf8')) as ManifestFile\n\n const { skills: selected } = selectSkills(root, config)\n const selectedSet = new Set(selected)\n const installed = Object.keys(manifest.skills)\n\n // Resolve each harness's skills dir once (used when removing skills and harnesses).\n const dirByHarness = new Map<string, string | null>()\n for (const h of new Set([...prevHarnesses, ...(config.harnesses ?? [])]))\n dirByHarness.set(h, harnessSkillsDir(root, h))\n\n // 1. Uninstall skills no longer selected.\n for (const s of installed) {\n if (selectedSet.has(s)) continue\n rmSync(join(out, '.ai', 'skills', s), { recursive: true, force: true })\n rmSync(join(out, '.ai', '.base', s), { recursive: true, force: true })\n delete manifest.skills[s]\n for (const dir of dirByHarness.values())\n if (dir) rmSync(join(out, dir, s), { recursive: true, force: true })\n }\n\n // 2. Install new + 3-way-merge surviving skills (shared with `sync`).\n let conflicts = 0\n for (const s of selected) {\n const r = reconcileSkill(root, out, config, s)\n manifest.skills[s] = { digest: r.digest, inputs: r.inputs }\n conflicts += r.conflicts\n }\n\n // 3. Drop skills dirs for harnesses removed entirely, then re-wire the surviving set.\n for (const h of prevHarnesses) {\n if ((config.harnesses ?? []).includes(h)) continue\n const dir = dirByHarness.get(h)\n if (dir && existsSync(join(out, dir))) rmSync(join(out, dir), { recursive: true, force: true })\n }\n wireHarnesses(root, out, config, selected, useCopy)\n\n writeManifest(out, config, manifest.skills)\n return conflicts\n}\n"],"mappings":"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","names":["readFileSync","readFileSync","writeFileSync","join","join","p","join","existsSync","join","readFileSync","join","writeFileSync","readFileSync","writeFileSync","existsSync","rmSync","join","relative","readFileSync","writeFileSync","existsSync","join","join","existsSync","readFileSync","writeFileSync","join","readFileSync","rmSync","relative","existsSync","writeFileSync","readFileSync","readdirSync","existsSync","mkdirSync","rmSync","symlinkSync","join","relative","join","existsSync","readdirSync","readFileSync","mkdirSync","relative","rmSync","symlinkSync","readFileSync","writeFileSync","mkdirSync","join","relative","readFileSync","join","mkdirSync","writeFileSync","relative","readFileSync","writeFileSync","existsSync","rmSync","cpSync","join","relative","existsSync","join","readFileSync","writeFileSync","cpSync","rmSync","relative","readFileSync"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -32,6 +32,7 @@ declare const FrameworkConfigSchema: z.ZodObject<{
|
|
|
32
32
|
defaultBranch?: string | undefined;
|
|
33
33
|
labels?: string[] | undefined;
|
|
34
34
|
}>>;
|
|
35
|
+
tiers: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
|
|
35
36
|
source: z.ZodOptional<z.ZodObject<{
|
|
36
37
|
path: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
37
38
|
repo: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
@@ -99,6 +100,7 @@ declare const FrameworkConfigSchema: z.ZodObject<{
|
|
|
99
100
|
defaultBranch?: string | undefined;
|
|
100
101
|
labels?: string[] | undefined;
|
|
101
102
|
} | undefined;
|
|
103
|
+
tiers?: string[] | undefined;
|
|
102
104
|
source?: {
|
|
103
105
|
path?: string | null | undefined;
|
|
104
106
|
repo?: string | null | undefined;
|
|
@@ -130,6 +132,7 @@ declare const FrameworkConfigSchema: z.ZodObject<{
|
|
|
130
132
|
defaultBranch?: string | undefined;
|
|
131
133
|
labels?: string[] | undefined;
|
|
132
134
|
} | undefined;
|
|
135
|
+
tiers?: string[] | undefined;
|
|
133
136
|
source?: {
|
|
134
137
|
path?: string | null | undefined;
|
|
135
138
|
repo?: string | null | undefined;
|
|
@@ -169,28 +172,28 @@ declare const AdapterSchema: z.ZodObject<{
|
|
|
169
172
|
name: string;
|
|
170
173
|
axis: string;
|
|
171
174
|
$schema?: string | undefined;
|
|
175
|
+
tiers?: {
|
|
176
|
+
skill: string;
|
|
177
|
+
tier: string;
|
|
178
|
+
}[] | undefined;
|
|
172
179
|
description?: string | undefined;
|
|
173
180
|
skillsDir?: string | undefined;
|
|
174
181
|
linkBase?: string | undefined;
|
|
175
182
|
augments?: string[] | undefined;
|
|
176
183
|
slots?: Record<string, string> | undefined;
|
|
177
|
-
tiers?: {
|
|
178
|
-
skill: string;
|
|
179
|
-
tier: string;
|
|
180
|
-
}[] | undefined;
|
|
181
184
|
}, {
|
|
182
185
|
name: string;
|
|
183
186
|
axis: string;
|
|
184
187
|
$schema?: string | undefined;
|
|
188
|
+
tiers?: {
|
|
189
|
+
skill: string;
|
|
190
|
+
tier: string;
|
|
191
|
+
}[] | undefined;
|
|
185
192
|
description?: string | undefined;
|
|
186
193
|
skillsDir?: string | undefined;
|
|
187
194
|
linkBase?: string | undefined;
|
|
188
195
|
augments?: string[] | undefined;
|
|
189
196
|
slots?: Record<string, string> | undefined;
|
|
190
|
-
tiers?: {
|
|
191
|
-
skill: string;
|
|
192
|
-
tier: string;
|
|
193
|
-
}[] | undefined;
|
|
194
197
|
}>;
|
|
195
198
|
/** core/ai/skills/tiers.json — declares the default tier set and per-skill axis requirements. */
|
|
196
199
|
declare const TiersSchema: z.ZodObject<{
|
|
@@ -262,6 +265,7 @@ interface SkillSelection {
|
|
|
262
265
|
skills: string[];
|
|
263
266
|
skipped: string[];
|
|
264
267
|
}
|
|
268
|
+
declare function loadTiers(root: string): Tiers;
|
|
265
269
|
declare function selectSkills(root: string, config: FrameworkConfig): SkillSelection;
|
|
266
270
|
|
|
267
271
|
interface MergeResult {
|
|
@@ -270,4 +274,4 @@ interface MergeResult {
|
|
|
270
274
|
}
|
|
271
275
|
declare function mergeFile(local: string, base: string, theirs: string): MergeResult;
|
|
272
276
|
|
|
273
|
-
export { type Adapter, AdapterSchema, type FrameworkConfig, FrameworkConfigSchema, type InputRef, type MergeResult, type Region, type RenderManifest, type RenderResult, SLOT_ANY, SLOT_OPEN, type SkillSelection, type Tiers, TiersSchema, mergeFile, renderSkill, selectSkills };
|
|
277
|
+
export { type Adapter, AdapterSchema, type FrameworkConfig, FrameworkConfigSchema, type InputRef, type MergeResult, type Region, type RenderManifest, type RenderResult, SLOT_ANY, SLOT_OPEN, type SkillSelection, type Tiers, TiersSchema, loadTiers, mergeFile, renderSkill, selectSkills };
|
package/dist/index.js
CHANGED
|
@@ -4,16 +4,18 @@ import {
|
|
|
4
4
|
SLOT_ANY,
|
|
5
5
|
SLOT_OPEN,
|
|
6
6
|
TiersSchema,
|
|
7
|
+
loadTiers,
|
|
7
8
|
mergeFile,
|
|
8
9
|
renderSkill,
|
|
9
10
|
selectSkills
|
|
10
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-QEUDIAAQ.js";
|
|
11
12
|
export {
|
|
12
13
|
AdapterSchema,
|
|
13
14
|
FrameworkConfigSchema,
|
|
14
15
|
SLOT_ANY,
|
|
15
16
|
SLOT_OPEN,
|
|
16
17
|
TiersSchema,
|
|
18
|
+
loadTiers,
|
|
17
19
|
mergeFile,
|
|
18
20
|
renderSkill,
|
|
19
21
|
selectSkills
|
package/package.json
CHANGED
|
@@ -76,6 +76,13 @@
|
|
|
76
76
|
},
|
|
77
77
|
"additionalProperties": false
|
|
78
78
|
},
|
|
79
|
+
"tiers": {
|
|
80
|
+
"type": "array",
|
|
81
|
+
"items": {
|
|
82
|
+
"type": "string"
|
|
83
|
+
},
|
|
84
|
+
"description": "Opt-in tiers to install in addition to the defaults (e.g. [\"framework\", \"automation\"])."
|
|
85
|
+
},
|
|
79
86
|
"source": {
|
|
80
87
|
"type": "object",
|
|
81
88
|
"properties": {
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/render.ts","../src/core/contracts.ts","../src/core/select.ts","../src/core/merge.ts"],"sourcesContent":["// Pure skill renderer — the heart of the framework. No I/O beyond reading source\n// files; returns { rendered, manifest, digest }. Kept dependency-light (node builtins\n// + a type-only contract import) because it runs in consumer repos, in CI, and inside\n// the improve-framework skill.\n//\n// Properties (proven in docs/render-model.md and asserted by the gate): convergence,\n// determinism, provenance, per-skill digest scoping.\nimport { readFileSync, existsSync } from 'node:fs'\nimport { join, relative } from 'node:path'\nimport { createHash } from 'node:crypto'\nimport type { FrameworkConfig } from './contracts.js'\n\nconst AXES = ['orm', 'ui', 'stack'] as const\ntype Axis = (typeof AXES)[number]\n\nconst sha = (s: string): string => createHash('sha256').update(s).digest('hex').slice(0, 12)\nconst norm = (s: string): string => s.replace(/\\r\\n/g, '\\n')\n\nconst OPEN = /^<!--\\s*SLOT:([\\w.-]+)\\s*-->$/\nconst CLOSE = /^<!--\\s*\\/SLOT:([\\w.-]+)\\s*-->$/\n\n// Shared, single source of truth for what a slot marker is — imported by the gate so\n// the gate and the renderer can never disagree (a slot is a marker ALONE ON ITS OWN\n// LINE; `SLOT:` mentioned in prose/backticks is not a slot and is never touched).\nexport const SLOT_OPEN = OPEN\nexport const SLOT_ANY = /^<!--\\s*\\/?SLOT:[\\w.-]+\\s*-->$/\n\nexport interface InputRef {\n path: string\n sha: string\n}\n\nexport interface Region {\n source: string\n adapter: string | null\n slot: string | null\n startLine: number\n endLine: number\n}\n\nexport interface RenderManifest {\n skill: string\n selection: Partial<Record<Axis, string>>\n digest: string\n note: string\n inputs: InputRef[]\n regions: Region[]\n}\n\nexport interface RenderResult {\n rendered: string\n manifest: RenderManifest\n digest: string\n}\n\ninterface SlotProvider {\n adapter: string\n axis: Axis\n source: string\n content: string\n}\n\nexport function renderSkill(root: string, config: FrameworkConfig, skill: string): RenderResult {\n const rel = (p: string): string => relative(root, p)\n\n // Active adapter per axis -> slot lookup (no inputs counted here).\n const selected: Partial<Record<Axis, string>> = {}\n for (const axis of AXES) {\n const value = config[axis]\n if (value) selected[axis] = value\n }\n\n const slotProviders: Record<string, SlotProvider> = {}\n for (const [axis, adapter] of Object.entries(selected) as [Axis, string][]) {\n const adDir = join(root, 'adapters', axis, adapter)\n const adPath = join(adDir, 'adapter.json')\n if (!existsSync(adPath)) continue\n const ad = JSON.parse(readFileSync(adPath, 'utf8')) as { slots?: Record<string, string> }\n for (const [slot, file] of Object.entries(ad.slots ?? {})) {\n const fp = join(adDir, file)\n const content = norm(readFileSync(fp, 'utf8')).replace(/\\s+$/, '') + '\\n'\n slotProviders[slot] = { adapter, axis, source: rel(fp), content }\n }\n }\n\n const genPath = join(root, 'core/ai/skills', skill, 'SKILL.md')\n const generic = norm(readFileSync(genPath, 'utf8'))\n\n // Inputs = only files that actually compose THIS skill (generic + filled fragments).\n const inputs: InputRef[] = [{ path: rel(genPath), sha: sha(generic) }]\n const seenInput = new Set<string>([rel(genPath)])\n\n const lines = generic.split('\\n')\n const out: string[] = []\n const regions: Region[] = []\n let bodyLine = 0\n const push = (line: string, source: string, meta?: { adapter: string; slot: string }): void => {\n out.push(line)\n bodyLine++\n const last = regions[regions.length - 1]\n const slot = meta?.slot ?? null\n if (last && last.source === source && last.slot === slot && last.endLine === bodyLine - 1) {\n last.endLine = bodyLine\n } else {\n regions.push({ source, adapter: meta?.adapter ?? null, slot, startLine: bodyLine, endLine: bodyLine })\n }\n }\n\n let i = 0\n while (i < lines.length) {\n const current = lines[i] as string\n const open = current.match(OPEN)\n if (open) {\n const slot = open[1] as string\n let j = i + 1\n while (\n j < lines.length &&\n !(CLOSE.test(lines[j] as string) && (lines[j] as string).match(CLOSE)![1] === slot)\n )\n j++\n const provider = slotProviders[slot]\n if (provider) {\n if (!seenInput.has(provider.source)) {\n seenInput.add(provider.source)\n inputs.push({ path: provider.source, sha: sha(provider.content) })\n }\n for (const cl of provider.content.replace(/\\n$/, '').split('\\n')) {\n push(cl, provider.source, { adapter: provider.adapter, slot })\n }\n } // no provider (axis unselected, or active adapter omits this slot) -> prune\n i = j + 1\n continue\n }\n push(current, rel(genPath))\n i++\n }\n\n const sortedInputs = [...inputs].sort((a, b) => a.path.localeCompare(b.path))\n const digest = sha(JSON.stringify(sortedInputs))\n const header = `<!-- generated by aef render — do not hand-edit; use the improve-framework skill or edit the framework source. digest:${digest} -->`\n const rendered = header + '\\n\\n' + out.join('\\n') + '\\n'\n\n const manifest: RenderManifest = {\n skill,\n selection: selected,\n digest,\n note: 'region line numbers are body-relative (line 1 = first line after the 2-line header); digest covers consumed inputs only',\n inputs: sortedInputs,\n regions,\n }\n return { rendered, manifest, digest }\n}\n","// Typed contracts — the single source of truth for every config/adapter shape the\n// framework reads. zod gives us (1) runtime validation in the CLI, (2) inferred TS\n// types for the codebase, and (3) JSON Schema (see scripts/gen-schemas.ts) published\n// under schemas/ for editor/CI validation. Change a shape here and regenerate.\nimport { z } from 'zod'\n\nconst slotName = z\n .string()\n .regex(/^[a-z][\\w-]*\\.[a-z][\\w-]*$/, \"slot names are '<axis>.<key>', e.g. 'orm.cheatsheet'\")\n\n/** Per-consumer configuration the renderer, init/sync, and skills all read. */\nexport const FrameworkConfigSchema = z\n .object({\n $schema: z.string().optional(),\n projectName: z.string().describe('Substituted for {{PROJECT_NAME}} in templates.').optional(),\n harnesses: z\n .array(z.string())\n .min(1)\n .describe('Active harness adapters; each wires its files + skills dir.'),\n orm: z.string().nullable().describe('Selected ORM adapter, or null to omit ORM skills.').optional(),\n ui: z.string().nullable().optional(),\n stack: z.string().nullable().optional(),\n paths: z\n .object({\n modulesRoot: z.string().optional(),\n specsRoot: z.string().optional(),\n testsRoot: z.string().optional(),\n })\n .strict()\n .optional(),\n validation: z.array(z.string()).describe('Commands skills run as the verification gate.').optional(),\n git: z\n .object({\n defaultBranch: z.string().optional(),\n labels: z.array(z.string()).optional(),\n })\n .strict()\n .optional(),\n source: z\n .object({\n path: z\n .string()\n .nullable()\n .describe('Local checkout path; if null, clone repo on demand.')\n .optional(),\n repo: z.string().nullable().optional(),\n })\n .strict()\n .describe('Where improve-framework finds the framework SOURCE.')\n .optional(),\n feedback: z\n .object({\n capture: z.boolean().default(true).describe('Write scope-tagged lessons locally; zero egress.'),\n upstream: z\n .object({\n mode: z.enum(['scheduled-pr', 'prompt', 'off']).default('scheduled-pr'),\n channel: z.enum(['pr', 'issue', 'fork']).default('pr'),\n schedule: z.string().default('weekly'),\n sanitize: z.boolean().default(true),\n requireHumanApproval: z.boolean().default(true),\n })\n .strict()\n .optional(),\n })\n .strict()\n .optional(),\n })\n .strict()\n\n/** An adapter declares which skills it augments and the slot content it provides. */\nexport const AdapterSchema = z\n .object({\n $schema: z.string().optional(),\n name: z.string().describe(\"Adapter id, e.g. 'drizzle'.\"),\n axis: z.string().describe('Variation family: orm | ui | stack | harness.'),\n description: z.string().optional(),\n skillsDir: z.string().describe('Harness only: directory the per-skill links go in.').optional(),\n linkBase: z.string().describe('Harness only: relative link target base from skillsDir.').optional(),\n augments: z.array(z.string()).describe('Skill ids this adapter contributes slot content to.').optional(),\n slots: z\n .record(slotName, z.string())\n .describe('slotName -> fragment path, relative to the adapter dir.')\n .optional(),\n tiers: z\n .array(z.object({ skill: z.string(), tier: z.string() }).strict())\n .describe('Optional skills this adapter adds, and the tier each joins.')\n .optional(),\n })\n .strict()\n\n/** core/ai/skills/tiers.json — declares the default tier set and per-skill axis requirements. */\nexport const TiersSchema = z\n .object({\n default: z.array(z.string()),\n tiers: z.record(z.string(), z.object({ skills: z.array(z.string()) }).passthrough()),\n requires: z.record(z.string(), z.string()).optional(),\n })\n .passthrough()\n\nexport type FrameworkConfig = z.infer<typeof FrameworkConfigSchema>\nexport type Adapter = z.infer<typeof AdapterSchema>\nexport type Tiers = z.infer<typeof TiersSchema>\n","// Tier resolution — turns the configured axis selections into the converged skill set.\n// A skill whose required axis is unconfigured is skipped (reported, not errored).\nimport { readFileSync } from 'node:fs'\nimport { join } from 'node:path'\nimport type { FrameworkConfig } from './contracts.js'\nimport { TiersSchema } from './contracts.js'\n\nexport interface SkillSelection {\n skills: string[]\n skipped: string[]\n}\n\nexport function selectSkills(root: string, config: FrameworkConfig): SkillSelection {\n const tiers = TiersSchema.parse(JSON.parse(readFileSync(join(root, 'core/ai/skills/tiers.json'), 'utf8')))\n const requires = tiers.requires ?? {}\n\n const candidates: string[] = []\n for (const t of tiers.default)\n for (const s of tiers.tiers[t]?.skills ?? []) if (!candidates.includes(s)) candidates.push(s)\n\n const skills: string[] = []\n const skipped: string[] = []\n for (const s of candidates) {\n const axis = requires[s]\n if (axis && !config[axis as keyof FrameworkConfig]) skipped.push(`${s} (needs ${axis})`)\n else skills.push(s)\n }\n return { skills: skills.sort(), skipped }\n}\n","// 3-way merge delegated to git — no custom merge engine. BASE = last render,\n// LOCAL = on-disk (with consumer edits), THEIRS = fresh framework render.\n// Returns the merged text and the conflict count git reports.\nimport { writeFileSync, mkdtempSync, rmSync } from 'node:fs'\nimport { join } from 'node:path'\nimport { tmpdir } from 'node:os'\nimport { spawnSync } from 'node:child_process'\n\nexport interface MergeResult {\n merged: string\n conflicts: number\n}\n\nexport function mergeFile(local: string, base: string, theirs: string): MergeResult {\n const dir = mkdtempSync(join(tmpdir(), 'agentic-merge-'))\n const lp = join(dir, 'local')\n const bp = join(dir, 'base')\n const tp = join(dir, 'theirs')\n writeFileSync(lp, local)\n writeFileSync(bp, base)\n writeFileSync(tp, theirs)\n const r = spawnSync(\n 'git',\n [\n 'merge-file',\n '-p',\n '-L',\n 'ours (your local edits)',\n '-L',\n 'base (last sync)',\n '-L',\n 'theirs (framework update)',\n lp,\n bp,\n tp,\n ],\n { encoding: 'utf8' },\n )\n rmSync(dir, { recursive: true, force: true })\n if (r.status === null || r.status < 0 || r.status >= 255)\n throw new Error(`git merge-file failed: ${r.stderr || String(r.error)}`)\n return { merged: r.stdout, conflicts: r.status }\n}\n"],"mappings":";AAOA,SAAS,cAAc,kBAAkB;AACzC,SAAS,MAAM,gBAAgB;AAC/B,SAAS,kBAAkB;AAG3B,IAAM,OAAO,CAAC,OAAO,MAAM,OAAO;AAGlC,IAAM,MAAM,CAAC,MAAsB,WAAW,QAAQ,EAAE,OAAO,CAAC,EAAE,OAAO,KAAK,EAAE,MAAM,GAAG,EAAE;AAC3F,IAAM,OAAO,CAAC,MAAsB,EAAE,QAAQ,SAAS,IAAI;AAE3D,IAAM,OAAO;AACb,IAAM,QAAQ;AAKP,IAAM,YAAY;AAClB,IAAM,WAAW;AAqCjB,SAAS,YAAY,MAAc,QAAyB,OAA6B;AAC9F,QAAM,MAAM,CAAC,MAAsB,SAAS,MAAM,CAAC;AAGnD,QAAM,WAA0C,CAAC;AACjD,aAAW,QAAQ,MAAM;AACvB,UAAM,QAAQ,OAAO,IAAI;AACzB,QAAI,MAAO,UAAS,IAAI,IAAI;AAAA,EAC9B;AAEA,QAAM,gBAA8C,CAAC;AACrD,aAAW,CAAC,MAAM,OAAO,KAAK,OAAO,QAAQ,QAAQ,GAAuB;AAC1E,UAAM,QAAQ,KAAK,MAAM,YAAY,MAAM,OAAO;AAClD,UAAM,SAAS,KAAK,OAAO,cAAc;AACzC,QAAI,CAAC,WAAW,MAAM,EAAG;AACzB,UAAM,KAAK,KAAK,MAAM,aAAa,QAAQ,MAAM,CAAC;AAClD,eAAW,CAAC,MAAM,IAAI,KAAK,OAAO,QAAQ,GAAG,SAAS,CAAC,CAAC,GAAG;AACzD,YAAM,KAAK,KAAK,OAAO,IAAI;AAC3B,YAAM,UAAU,KAAK,aAAa,IAAI,MAAM,CAAC,EAAE,QAAQ,QAAQ,EAAE,IAAI;AACrE,oBAAc,IAAI,IAAI,EAAE,SAAS,MAAM,QAAQ,IAAI,EAAE,GAAG,QAAQ;AAAA,IAClE;AAAA,EACF;AAEA,QAAM,UAAU,KAAK,MAAM,kBAAkB,OAAO,UAAU;AAC9D,QAAM,UAAU,KAAK,aAAa,SAAS,MAAM,CAAC;AAGlD,QAAM,SAAqB,CAAC,EAAE,MAAM,IAAI,OAAO,GAAG,KAAK,IAAI,OAAO,EAAE,CAAC;AACrE,QAAM,YAAY,oBAAI,IAAY,CAAC,IAAI,OAAO,CAAC,CAAC;AAEhD,QAAM,QAAQ,QAAQ,MAAM,IAAI;AAChC,QAAM,MAAgB,CAAC;AACvB,QAAM,UAAoB,CAAC;AAC3B,MAAI,WAAW;AACf,QAAM,OAAO,CAAC,MAAc,QAAgB,SAAmD;AAC7F,QAAI,KAAK,IAAI;AACb;AACA,UAAM,OAAO,QAAQ,QAAQ,SAAS,CAAC;AACvC,UAAM,OAAO,MAAM,QAAQ;AAC3B,QAAI,QAAQ,KAAK,WAAW,UAAU,KAAK,SAAS,QAAQ,KAAK,YAAY,WAAW,GAAG;AACzF,WAAK,UAAU;AAAA,IACjB,OAAO;AACL,cAAQ,KAAK,EAAE,QAAQ,SAAS,MAAM,WAAW,MAAM,MAAM,WAAW,UAAU,SAAS,SAAS,CAAC;AAAA,IACvG;AAAA,EACF;AAEA,MAAI,IAAI;AACR,SAAO,IAAI,MAAM,QAAQ;AACvB,UAAM,UAAU,MAAM,CAAC;AACvB,UAAM,OAAO,QAAQ,MAAM,IAAI;AAC/B,QAAI,MAAM;AACR,YAAM,OAAO,KAAK,CAAC;AACnB,UAAI,IAAI,IAAI;AACZ,aACE,IAAI,MAAM,UACV,EAAE,MAAM,KAAK,MAAM,CAAC,CAAW,KAAM,MAAM,CAAC,EAAa,MAAM,KAAK,EAAG,CAAC,MAAM;AAE9E;AACF,YAAM,WAAW,cAAc,IAAI;AACnC,UAAI,UAAU;AACZ,YAAI,CAAC,UAAU,IAAI,SAAS,MAAM,GAAG;AACnC,oBAAU,IAAI,SAAS,MAAM;AAC7B,iBAAO,KAAK,EAAE,MAAM,SAAS,QAAQ,KAAK,IAAI,SAAS,OAAO,EAAE,CAAC;AAAA,QACnE;AACA,mBAAW,MAAM,SAAS,QAAQ,QAAQ,OAAO,EAAE,EAAE,MAAM,IAAI,GAAG;AAChE,eAAK,IAAI,SAAS,QAAQ,EAAE,SAAS,SAAS,SAAS,KAAK,CAAC;AAAA,QAC/D;AAAA,MACF;AACA,UAAI,IAAI;AACR;AAAA,IACF;AACA,SAAK,SAAS,IAAI,OAAO,CAAC;AAC1B;AAAA,EACF;AAEA,QAAM,eAAe,CAAC,GAAG,MAAM,EAAE,KAAK,CAAC,GAAG,MAAM,EAAE,KAAK,cAAc,EAAE,IAAI,CAAC;AAC5E,QAAM,SAAS,IAAI,KAAK,UAAU,YAAY,CAAC;AAC/C,QAAM,SAAS,8HAAyH,MAAM;AAC9I,QAAM,WAAW,SAAS,SAAS,IAAI,KAAK,IAAI,IAAI;AAEpD,QAAM,WAA2B;AAAA,IAC/B;AAAA,IACA,WAAW;AAAA,IACX;AAAA,IACA,MAAM;AAAA,IACN,QAAQ;AAAA,IACR;AAAA,EACF;AACA,SAAO,EAAE,UAAU,UAAU,OAAO;AACtC;;;ACnJA,SAAS,SAAS;AAElB,IAAM,WAAW,EACd,OAAO,EACP,MAAM,8BAA8B,sDAAsD;AAGtF,IAAM,wBAAwB,EAClC,OAAO;AAAA,EACN,SAAS,EAAE,OAAO,EAAE,SAAS;AAAA,EAC7B,aAAa,EAAE,OAAO,EAAE,SAAS,gDAAgD,EAAE,SAAS;AAAA,EAC5F,WAAW,EACR,MAAM,EAAE,OAAO,CAAC,EAChB,IAAI,CAAC,EACL,SAAS,6DAA6D;AAAA,EACzE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,mDAAmD,EAAE,SAAS;AAAA,EAClG,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,EACnC,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,EACtC,OAAO,EACJ,OAAO;AAAA,IACN,aAAa,EAAE,OAAO,EAAE,SAAS;AAAA,IACjC,WAAW,EAAE,OAAO,EAAE,SAAS;AAAA,IAC/B,WAAW,EAAE,OAAO,EAAE,SAAS;AAAA,EACjC,CAAC,EACA,OAAO,EACP,SAAS;AAAA,EACZ,YAAY,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS,+CAA+C,EAAE,SAAS;AAAA,EACnG,KAAK,EACF,OAAO;AAAA,IACN,eAAe,EAAE,OAAO,EAAE,SAAS;AAAA,IACnC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS;AAAA,EACvC,CAAC,EACA,OAAO,EACP,SAAS;AAAA,EACZ,QAAQ,EACL,OAAO;AAAA,IACN,MAAM,EACH,OAAO,EACP,SAAS,EACT,SAAS,qDAAqD,EAC9D,SAAS;AAAA,IACZ,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS;AAAA,EACvC,CAAC,EACA,OAAO,EACP,SAAS,qDAAqD,EAC9D,SAAS;AAAA,EACZ,UAAU,EACP,OAAO;AAAA,IACN,SAAS,EAAE,QAAQ,EAAE,QAAQ,IAAI,EAAE,SAAS,kDAAkD;AAAA,IAC9F,UAAU,EACP,OAAO;AAAA,MACN,MAAM,EAAE,KAAK,CAAC,gBAAgB,UAAU,KAAK,CAAC,EAAE,QAAQ,cAAc;AAAA,MACtE,SAAS,EAAE,KAAK,CAAC,MAAM,SAAS,MAAM,CAAC,EAAE,QAAQ,IAAI;AAAA,MACrD,UAAU,EAAE,OAAO,EAAE,QAAQ,QAAQ;AAAA,MACrC,UAAU,EAAE,QAAQ,EAAE,QAAQ,IAAI;AAAA,MAClC,sBAAsB,EAAE,QAAQ,EAAE,QAAQ,IAAI;AAAA,IAChD,CAAC,EACA,OAAO,EACP,SAAS;AAAA,EACd,CAAC,EACA,OAAO,EACP,SAAS;AACd,CAAC,EACA,OAAO;AAGH,IAAM,gBAAgB,EAC1B,OAAO;AAAA,EACN,SAAS,EAAE,OAAO,EAAE,SAAS;AAAA,EAC7B,MAAM,EAAE,OAAO,EAAE,SAAS,6BAA6B;AAAA,EACvD,MAAM,EAAE,OAAO,EAAE,SAAS,+CAA+C;AAAA,EACzE,aAAa,EAAE,OAAO,EAAE,SAAS;AAAA,EACjC,WAAW,EAAE,OAAO,EAAE,SAAS,oDAAoD,EAAE,SAAS;AAAA,EAC9F,UAAU,EAAE,OAAO,EAAE,SAAS,yDAAyD,EAAE,SAAS;AAAA,EAClG,UAAU,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS,qDAAqD,EAAE,SAAS;AAAA,EACvG,OAAO,EACJ,OAAO,UAAU,EAAE,OAAO,CAAC,EAC3B,SAAS,yDAAyD,EAClE,SAAS;AAAA,EACZ,OAAO,EACJ,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,GAAG,MAAM,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,CAAC,EAChE,SAAS,6DAA6D,EACtE,SAAS;AACd,CAAC,EACA,OAAO;AAGH,IAAM,cAAc,EACxB,OAAO;AAAA,EACN,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC;AAAA,EAC3B,OAAO,EAAE,OAAO,EAAE,OAAO,GAAG,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC,EAAE,YAAY,CAAC;AAAA,EACnF,UAAU,EAAE,OAAO,EAAE,OAAO,GAAG,EAAE,OAAO,CAAC,EAAE,SAAS;AACtD,CAAC,EACA,YAAY;;;AC/Ff,SAAS,gBAAAA,qBAAoB;AAC7B,SAAS,QAAAC,aAAY;AASd,SAAS,aAAa,MAAc,QAAyC;AAClF,QAAM,QAAQ,YAAY,MAAM,KAAK,MAAMC,cAAaC,MAAK,MAAM,2BAA2B,GAAG,MAAM,CAAC,CAAC;AACzG,QAAM,WAAW,MAAM,YAAY,CAAC;AAEpC,QAAM,aAAuB,CAAC;AAC9B,aAAW,KAAK,MAAM;AACpB,eAAW,KAAK,MAAM,MAAM,CAAC,GAAG,UAAU,CAAC,EAAG,KAAI,CAAC,WAAW,SAAS,CAAC,EAAG,YAAW,KAAK,CAAC;AAE9F,QAAM,SAAmB,CAAC;AAC1B,QAAM,UAAoB,CAAC;AAC3B,aAAW,KAAK,YAAY;AAC1B,UAAM,OAAO,SAAS,CAAC;AACvB,QAAI,QAAQ,CAAC,OAAO,IAA6B,EAAG,SAAQ,KAAK,GAAG,CAAC,WAAW,IAAI,GAAG;AAAA,QAClF,QAAO,KAAK,CAAC;AAAA,EACpB;AACA,SAAO,EAAE,QAAQ,OAAO,KAAK,GAAG,QAAQ;AAC1C;;;ACzBA,SAAS,eAAe,aAAa,cAAc;AACnD,SAAS,QAAAC,aAAY;AACrB,SAAS,cAAc;AACvB,SAAS,iBAAiB;AAOnB,SAAS,UAAU,OAAe,MAAc,QAA6B;AAClF,QAAM,MAAM,YAAYA,MAAK,OAAO,GAAG,gBAAgB,CAAC;AACxD,QAAM,KAAKA,MAAK,KAAK,OAAO;AAC5B,QAAM,KAAKA,MAAK,KAAK,MAAM;AAC3B,QAAM,KAAKA,MAAK,KAAK,QAAQ;AAC7B,gBAAc,IAAI,KAAK;AACvB,gBAAc,IAAI,IAAI;AACtB,gBAAc,IAAI,MAAM;AACxB,QAAM,IAAI;AAAA,IACR;AAAA,IACA;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,EAAE,UAAU,OAAO;AAAA,EACrB;AACA,SAAO,KAAK,EAAE,WAAW,MAAM,OAAO,KAAK,CAAC;AAC5C,MAAI,EAAE,WAAW,QAAQ,EAAE,SAAS,KAAK,EAAE,UAAU;AACnD,UAAM,IAAI,MAAM,0BAA0B,EAAE,UAAU,OAAO,EAAE,KAAK,CAAC,EAAE;AACzE,SAAO,EAAE,QAAQ,EAAE,QAAQ,WAAW,EAAE,OAAO;AACjD;","names":["readFileSync","join","readFileSync","join","join"]}
|