@alpaca-software/40kdc-data 0.1.2 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/dist/abilities-resolver/resolver.d.ts +13 -4
- package/dist/abilities-resolver/resolver.d.ts.map +1 -1
- package/dist/abilities-resolver/resolver.js +22 -15
- package/dist/abilities-resolver/resolver.js.map +1 -1
- package/dist/audit-coverage.d.ts +78 -0
- package/dist/audit-coverage.d.ts.map +1 -0
- package/dist/audit-coverage.js +341 -0
- package/dist/audit-coverage.js.map +1 -0
- package/dist/author-batch.d.ts +147 -0
- package/dist/author-batch.d.ts.map +1 -0
- package/dist/author-batch.js +675 -0
- package/dist/author-batch.js.map +1 -0
- package/dist/author-input.d.ts +37 -0
- package/dist/author-input.d.ts.map +1 -0
- package/dist/author-input.js +162 -0
- package/dist/author-input.js.map +1 -0
- package/dist/cli.js +7 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/translate.d.ts.map +1 -1
- package/dist/commands/translate.js +9 -4
- package/dist/commands/translate.js.map +1 -1
- package/dist/cruncher/attribution.d.ts +66 -0
- package/dist/cruncher/attribution.d.ts.map +1 -0
- package/dist/cruncher/attribution.js +88 -0
- package/dist/cruncher/attribution.js.map +1 -0
- package/dist/cruncher/buffs.d.ts +23 -1
- package/dist/cruncher/buffs.d.ts.map +1 -1
- package/dist/cruncher/buffs.js +1 -1
- package/dist/cruncher/buffs.js.map +1 -1
- package/dist/cruncher/from-dsl.d.ts +32 -0
- package/dist/cruncher/from-dsl.d.ts.map +1 -1
- package/dist/cruncher/from-dsl.js +485 -40
- package/dist/cruncher/from-dsl.js.map +1 -1
- package/dist/cruncher/index.d.ts +1 -0
- package/dist/cruncher/index.d.ts.map +1 -1
- package/dist/cruncher/index.js +1 -0
- package/dist/cruncher/index.js.map +1 -1
- package/dist/data/bundle.generated.js +1 -1
- package/dist/data/bundle.generated.js.map +1 -1
- package/dist/data/collection.d.ts +9 -0
- package/dist/data/collection.d.ts.map +1 -1
- package/dist/data/collection.js +14 -0
- package/dist/data/collection.js.map +1 -1
- package/dist/data/dataset.d.ts +80 -2
- package/dist/data/dataset.d.ts.map +1 -1
- package/dist/data/dataset.js +143 -6
- package/dist/data/dataset.js.map +1 -1
- package/dist/data/entities.d.ts +2 -5
- package/dist/data/entities.d.ts.map +1 -1
- package/dist/data/entities.js.map +1 -1
- package/dist/data/index.d.ts +3 -2
- package/dist/data/index.d.ts.map +1 -1
- package/dist/data/index.js +1 -1
- package/dist/data/index.js.map +1 -1
- package/dist/data/roster-resolve.d.ts +26 -1
- package/dist/data/roster-resolve.d.ts.map +1 -1
- package/dist/data/roster-resolve.js +46 -0
- package/dist/data/roster-resolve.js.map +1 -1
- package/dist/export/index.d.ts +1 -0
- package/dist/export/index.d.ts.map +1 -1
- package/dist/export/index.js +3 -0
- package/dist/export/index.js.map +1 -1
- package/dist/export/rosterizer.d.ts +3 -0
- package/dist/export/rosterizer.d.ts.map +1 -0
- package/dist/export/rosterizer.js +144 -0
- package/dist/export/rosterizer.js.map +1 -0
- package/dist/export/serializer.d.ts +1 -1
- package/dist/export/serializer.d.ts.map +1 -1
- package/dist/export/serializer.js.map +1 -1
- package/dist/gen-conformance.js +212 -11
- package/dist/gen-conformance.js.map +1 -1
- package/dist/import/gw.d.ts +69 -0
- package/dist/import/gw.d.ts.map +1 -0
- package/dist/import/gw.js +245 -0
- package/dist/import/gw.js.map +1 -0
- package/dist/import/import-roster.d.ts +52 -3
- package/dist/import/import-roster.d.ts.map +1 -1
- package/dist/import/import-roster.js +114 -4
- package/dist/import/import-roster.js.map +1 -1
- package/dist/import/index.d.ts +2 -2
- package/dist/import/index.d.ts.map +1 -1
- package/dist/import/index.js +1 -1
- package/dist/import/index.js.map +1 -1
- package/dist/import/listforge.d.ts.map +1 -1
- package/dist/import/listforge.js +15 -1
- package/dist/import/listforge.js.map +1 -1
- package/dist/import/newrecruit-text.d.ts +3 -0
- package/dist/import/newrecruit-text.d.ts.map +1 -1
- package/dist/import/newrecruit-text.js +6 -0
- package/dist/import/newrecruit-text.js.map +1 -1
- package/dist/import/newrecruit-wtc.d.ts.map +1 -1
- package/dist/import/newrecruit-wtc.js +10 -7
- package/dist/import/newrecruit-wtc.js.map +1 -1
- package/dist/import/rosterizer.d.ts +70 -0
- package/dist/import/rosterizer.d.ts.map +1 -0
- package/dist/import/rosterizer.js +348 -0
- package/dist/import/rosterizer.js.map +1 -0
- package/dist/import/types.d.ts +1 -1
- package/dist/import/types.d.ts.map +1 -1
- package/dist/import/types.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/migrations/2026-weapon-keywords.js +4 -0
- package/dist/migrations/2026-weapon-keywords.js.map +1 -1
- package/dist/runner.d.ts +38 -0
- package/dist/runner.d.ts.map +1 -0
- package/dist/runner.js +492 -0
- package/dist/runner.js.map +1 -0
- package/dist/scrub-ip.d.ts +14 -0
- package/dist/scrub-ip.d.ts.map +1 -0
- package/dist/scrub-ip.js +88 -0
- package/dist/scrub-ip.js.map +1 -0
- package/package.json +9 -2
- package/schemas/core/roster.schema.json +3 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"audit-coverage.js","sourceRoot":"","sources":["../src/audit-coverage.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Ability-coverage audit: measure how much of the community-authored ability\n * data actually translates into cruncher buffs, per faction.\n *\n * The buff layer only interprets a subset of the ability DSL (see\n * `cruncher/from-dsl.ts`). An ability that doesn't translate is inert in Salvo —\n * the projection silently falls back to raw-statline math. This tool runs the\n * *real* translator (`effectToBuffs`) over every authored ability, under both\n * the attacker and target perspectives and across every phase, and classifies\n * each entry as:\n *\n * - **offensive** — yields ≥1 attacker-side buff (auto-applied or activatable)\n * - **defensive** — yields ≥1 target-side buff\n * - **inert** — neither; the effect is `unsupported` and/or a stub\n *\n * It also tallies the verbatim-GW-text leak (`community_notes` carrying an\n * `\"Original:\"` dump) and the explicit `\"skipped for damage calc\"` defensive\n * entries, and histograms the `unsupported.reason` strings so the output is a\n * directly-actionable authoring worklist.\n *\n * Usage:\n * npx tsx tools/src/audit-coverage.ts (pretty report to stdout)\n * npx tsx tools/src/audit-coverage.ts --json (machine-readable)\n * npx tsx tools/src/audit-coverage.ts --write (also emit data/_audit/*)\n *\n * Wired as `40kdc-validate audit-coverage` and `npm run audit:coverage`.\n */\nimport { readdirSync, readFileSync, writeFileSync, mkdirSync } from \"node:fs\";\nimport { resolve, basename } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport chalk from \"chalk\";\nimport { effectToBuffs } from \"./cruncher/from-dsl.js\";\nimport type { BuffSource, EngineContext } from \"./cruncher/buffs.js\";\nimport type { Phase } from \"./generated.js\";\n\nconst __dirname = fileURLToPath(new URL(\".\", import.meta.url));\nconst DATA_ROOT = resolve(__dirname, \"../../data\");\nconst ENRICHMENT_ROOT = resolve(DATA_ROOT, \"enrichment\");\nconst AUDIT_DIR = resolve(DATA_ROOT, \"_audit\");\n\nconst PHASES: Phase[] = [\"command\", \"movement\", \"shooting\", \"charge\", \"fight\"];\n\n/** Shape of an authored ability entry (only the fields this audit reads). */\ninterface AbilityEntry {\n ability_id: string;\n name?: string;\n ability_type?: string;\n community_notes?: string;\n effect?: unknown;\n}\n\nexport interface FactionCoverage {\n faction: string;\n total: number;\n offensive: number;\n defensive: number;\n /** Produces neither an offensive nor a defensive buff. */\n inert: number;\n /** `community_notes` flags it an auto-generated stub / partial. */\n stub: number;\n /**\n * Structurally a placeholder: the effect tree contains a modifier-bearing\n * node with an empty `modifier: {}` (the original pass's untyped stub, e.g.\n * `stat-modifier {}`). This — not `inert` — is the authoring worklist: an\n * inert-but-correctly-typed ability (movement, objective control) is *done*;\n * an empty-modifier node is a gap regardless of who consumes it.\n */\n stubStructural: number;\n /** `community_notes` carries a verbatim GW `\"Original:\"` text dump (IP leak). */\n gwTextLeak: number;\n /** Explicitly tagged `\"defensive ability (skipped for damage calc)\"`. */\n defensiveSkipped: number;\n}\n\n/**\n * One named gap. Carries the ability's identity and current shape so the gap is\n * self-describing on the consumer end (the fan-out joins the source rule; the\n * editor / downstream tools can list \"what's unauthored\" without re-deriving).\n */\nexport interface WorklistEntry {\n faction: string;\n ability_id: string;\n name: string;\n /** Top-level effect type as authored today (the \"shape\"), or `null` if absent. */\n shape: string | null;\n /** Has an empty-modifier placeholder node somewhere in its effect tree. */\n stub: boolean;\n offensive: boolean;\n defensive: boolean;\n /** Most-informative unsupported reason from the attacker walk, if any. */\n gap: string | null;\n}\n\nexport interface CoverageReport {\n factions: FactionCoverage[];\n totals: Omit<FactionCoverage, \"faction\">;\n /** `unsupported.reason` (normalized) → count, descending. */\n unsupportedReasons: { reason: string; count: number }[];\n /** Per-ability named gaps — the authoring worklist. */\n worklist: WorklistEntry[];\n}\n\n/**\n * Build a permissive context for `phase` — every situational flag set so that\n * conditionals gated on stationary/charged/half-range/attachment can fire. We\n * want \"could this ability *ever* produce a buff\", not \"does it fire right now\".\n * Keyword-specific conditions (`target-has-keyword`) still evaluate `\"unknown\"`\n * since no concrete target exists; those surface in the reason histogram.\n */\nfunction permissiveContext(phase: Phase): EngineContext {\n return {\n phase,\n attackerStationary: true,\n attackerCharged: true,\n withinHalfRange: true,\n attackerInCover: true,\n targetInCover: true,\n attackerAttached: true,\n attackerKeywords: [],\n targetKeywords: [],\n };\n}\n\n/** Map an `ability_type` to the buff-source kind (only labels; not load-bearing here). */\nfunction sourceKind(abilityType: string | undefined): BuffSource {\n const kind =\n abilityType === \"faction\"\n ? \"army\"\n : abilityType === \"detachment\"\n ? \"detachment\"\n : abilityType === \"stratagem\"\n ? \"detachment-stratagem\"\n : \"unit\";\n return { kind: \"ability\", abilityId: \"audit\", abilityKind: kind };\n}\n\n/**\n * Keep reasons verbatim — the quoted specifics (which effect type, which\n * operation) ARE the worklist signal. We only collapse the `subset \"…\"` half of\n * the re-roll reason, which is high-cardinality noise, while keeping the roll.\n */\nfunction normalizeReason(reason: string): string {\n return reason.replace(/\\(subset \"[^\"]*\"\\)/g, \"(subset …)\");\n}\n\n/**\n * Translate one ability under one perspective across all phases; return whether\n * it produced any buff, accumulating unsupported reasons into `reasonCounts`.\n */\nfunction producesBuff(\n effect: unknown,\n source: BuffSource,\n perspective: \"attacker\" | \"target\",\n reasonCounts: Map<string, number>,\n): boolean {\n let produced = false;\n for (const phase of PHASES) {\n const t = effectToBuffs(effect, source, permissiveContext(phase), perspective);\n if (t.applied.length > 0 || t.activatable.length > 0) produced = true;\n // Only attacker-perspective reasons feed the histogram — the target pass\n // re-walks the same tree and would double-count every offensive-only branch\n // as \"unsupported on defense\", which is noise for the worklist.\n if (perspective === \"attacker\") {\n for (const u of t.unsupported) {\n const key = normalizeReason(u.reason);\n reasonCounts.set(key, (reasonCounts.get(key) ?? 0) + 1);\n }\n }\n }\n return produced;\n}\n\n/**\n * Effect types that are pure flags — they carry no parameters, so an empty\n * `modifier: {}` is *correct*, not a stub (per `translate.ts`, these read no\n * modifier fields). Excluding them keeps the worklist from crying wolf on\n * legitimately-authored abilities like Deep Strike.\n */\nconst PARAMETERLESS_EFFECTS = new Set([\n \"deep-strike\",\n \"fallback-and-act\",\n \"fight-first\",\n \"fight-last\",\n \"fight-on-death\",\n \"shoot-on-death\",\n]);\n\n/**\n * True if any node in the effect tree is a *parameter-requiring* leaf left with\n * an empty `modifier: {}` — the original pass's untyped placeholder. Pure-flag\n * effects (see {@link PARAMETERLESS_EFFECTS}) are exempt.\n */\nexport function hasEmptyModifier(node: unknown): boolean {\n if (Array.isArray(node)) return node.some(hasEmptyModifier);\n if (typeof node !== \"object\" || node === null) return false;\n const rec = node as Record<string, unknown>;\n const mod = rec.modifier;\n if (\n typeof rec.type === \"string\" &&\n !PARAMETERLESS_EFFECTS.has(rec.type) &&\n mod !== undefined &&\n typeof mod === \"object\" &&\n mod !== null &&\n !Array.isArray(mod) &&\n Object.keys(mod).length === 0\n ) {\n return true;\n }\n return Object.values(rec).some(hasEmptyModifier);\n}\n\n/** Top-level effect type (the \"shape\") as authored today. */\nfunction shapeOf(effect: unknown): string | null {\n if (typeof effect === \"object\" && effect !== null && !Array.isArray(effect)) {\n const t = (effect as Record<string, unknown>).type;\n if (typeof t === \"string\") return t;\n }\n return null;\n}\n\n/** Compute coverage for a set of factions. Pure — IO lives in the command. */\nexport function computeCoverage(\n input: { faction: string; abilities: AbilityEntry[] }[],\n): CoverageReport {\n const reasonCounts = new Map<string, number>();\n const factions: FactionCoverage[] = [];\n const worklist: WorklistEntry[] = [];\n\n for (const { faction, abilities } of input) {\n const fc: FactionCoverage = {\n faction,\n total: abilities.length,\n offensive: 0,\n defensive: 0,\n inert: 0,\n stub: 0,\n stubStructural: 0,\n gwTextLeak: 0,\n defensiveSkipped: 0,\n };\n for (const a of abilities) {\n const notes = a.community_notes ?? \"\";\n if (/Original:/.test(notes)) fc.gwTextLeak++;\n if (/stub|partial/i.test(notes)) fc.stub++;\n if (/skipped for damage calc/i.test(notes)) fc.defensiveSkipped++;\n\n const source = sourceKind(a.ability_type);\n // De-dupe reasons within a single ability so a 5-phase walk doesn't count\n // the same unsupported branch five times.\n const perAbility = new Map<string, number>();\n const off = producesBuff(a.effect, source, \"attacker\", perAbility);\n const def = producesBuff(a.effect, source, \"target\", new Map());\n for (const [reason] of perAbility) {\n reasonCounts.set(reason, (reasonCounts.get(reason) ?? 0) + 1);\n }\n if (off) fc.offensive++;\n if (def) fc.defensive++;\n if (!off && !def) fc.inert++;\n\n const isStub = hasEmptyModifier(a.effect);\n if (isStub) fc.stubStructural++;\n\n worklist.push({\n faction,\n ability_id: a.ability_id,\n name: a.name ?? a.ability_id,\n shape: shapeOf(a.effect),\n stub: isStub,\n offensive: off,\n defensive: def,\n gap: perAbility.size > 0 ? [...perAbility.keys()][0] : null,\n });\n }\n factions.push(fc);\n }\n\n factions.sort((a, b) => a.faction.localeCompare(b.faction));\n\n const totals = factions.reduce(\n (acc, f) => {\n acc.total += f.total;\n acc.offensive += f.offensive;\n acc.defensive += f.defensive;\n acc.inert += f.inert;\n acc.stub += f.stub;\n acc.stubStructural += f.stubStructural;\n acc.gwTextLeak += f.gwTextLeak;\n acc.defensiveSkipped += f.defensiveSkipped;\n return acc;\n },\n { total: 0, offensive: 0, defensive: 0, inert: 0, stub: 0, stubStructural: 0, gwTextLeak: 0, defensiveSkipped: 0 },\n );\n\n const unsupportedReasons = [...reasonCounts.entries()]\n .map(([reason, count]) => ({ reason, count }))\n .sort((a, b) => b.count - a.count);\n\n return { factions, totals, unsupportedReasons, worklist };\n}\n\n/** Read every `data/enrichment/<faction>/abilities.json` (skips `_example`). */\nfunction loadFactions(): { faction: string; abilities: AbilityEntry[] }[] {\n const out: { faction: string; abilities: AbilityEntry[] }[] = [];\n for (const entry of readdirSync(ENRICHMENT_ROOT, { withFileTypes: true })) {\n if (!entry.isDirectory() || entry.name === \"_example\") continue;\n const file = resolve(ENRICHMENT_ROOT, entry.name, \"abilities.json\");\n let abilities: AbilityEntry[];\n try {\n abilities = JSON.parse(readFileSync(file, \"utf-8\"));\n } catch {\n continue; // no abilities.json in this folder\n }\n if (!Array.isArray(abilities)) continue;\n out.push({ faction: entry.name, abilities });\n }\n return out;\n}\n\nconst pct = (n: number, d: number): string => (d === 0 ? \"—\" : `${Math.round((100 * n) / d)}%`);\n\nfunction prettyReport(r: CoverageReport): string {\n const lines: string[] = [];\n lines.push(\"\");\n lines.push(chalk.bold(\"40kdc Ability Coverage Audit\"));\n lines.push(chalk.gray(\"─\".repeat(78)));\n lines.push(\n chalk.gray(\n \"faction\".padEnd(24) +\n \"total\".padStart(7) +\n \"off\".padStart(7) +\n \"def\".padStart(7) +\n \"inert\".padStart(7) +\n \"stub\".padStart(7) +\n \"leak\".padStart(7),\n ),\n );\n for (const f of r.factions) {\n const stubWarn = f.stubStructural > 0;\n const row =\n f.faction.padEnd(24) +\n String(f.total).padStart(7) +\n `${f.offensive}`.padStart(7) +\n `${f.defensive}`.padStart(7) +\n `${f.inert}`.padStart(7) +\n `${f.stubStructural}`.padStart(7) +\n `${f.gwTextLeak}`.padStart(7);\n lines.push(stubWarn ? chalk.yellow(row) : row);\n }\n lines.push(chalk.gray(\"─\".repeat(78)));\n const t = r.totals;\n lines.push(\n chalk.bold(\n \"TOTAL\".padEnd(24) +\n String(t.total).padStart(7) +\n `${t.offensive}`.padStart(7) +\n `${t.defensive}`.padStart(7) +\n `${t.inert}`.padStart(7) +\n `${t.stubStructural}`.padStart(7) +\n `${t.gwTextLeak}`.padStart(7),\n ),\n );\n lines.push(\"\");\n lines.push(\n `Offensive coverage: ${chalk.cyan(pct(t.offensive, t.total))} ` +\n `Defensive coverage: ${chalk.cyan(pct(t.defensive, t.total))} ` +\n `Inert: ${chalk.yellow(pct(t.inert, t.total))}`,\n );\n if (t.gwTextLeak > 0) {\n lines.push(chalk.red(`⚠ ${t.gwTextLeak} entries leak verbatim GW text (community_notes \"Original:\") — IP scrub needed (#20).`));\n }\n lines.push(chalk.gray(`${t.defensiveSkipped} entries tagged \"skipped for damage calc\" (defensive worklist, #23).`));\n lines.push(\"\");\n lines.push(chalk.bold(\"Top unsupported-effect reasons (offensive walk):\"));\n for (const { reason, count } of r.unsupportedReasons.slice(0, 15)) {\n lines.push(` ${String(count).padStart(5)} ${chalk.gray(reason)}`);\n }\n lines.push(\"\");\n return lines.join(\"\\n\");\n}\n\nfunction markdownReport(r: CoverageReport): string {\n const lines: string[] = [\n \"# Ability coverage audit\",\n \"\",\n \"Generated by `tools/src/audit-coverage.ts` (`npm run audit:coverage`). Counts\",\n \"abilities that translate into cruncher buffs via the real `effectToBuffs`\",\n \"(attacker + target perspective, all phases). `inert` = produces neither.\",\n \"\",\n \"| faction | total | offensive | defensive | inert | stub* | notes-stub | gw-leak | def-skipped |\",\n \"|---|--:|--:|--:|--:|--:|--:|--:|--:|\",\n ];\n for (const f of r.factions) {\n lines.push(\n `| ${f.faction} | ${f.total} | ${f.offensive} | ${f.defensive} | ${f.inert} | ${f.stubStructural} | ${f.stub} | ${f.gwTextLeak} | ${f.defensiveSkipped} |`,\n );\n }\n const t = r.totals;\n lines.push(\n `| **TOTAL** | **${t.total}** | **${t.offensive}** | **${t.defensive}** | **${t.inert}** | **${t.stubStructural}** | **${t.stub}** | **${t.gwTextLeak}** | **${t.defensiveSkipped}** |`,\n );\n lines.push(\"\", \"`stub*` = structural (empty-modifier placeholder node) — the authoring worklist. `notes-stub` = flagged in community_notes.\");\n lines.push(\"\", \"## Unsupported-effect reasons (offensive walk)\", \"\");\n for (const { reason, count } of r.unsupportedReasons) {\n lines.push(`- \\`${count}\\` — ${reason}`);\n }\n lines.push(\"\");\n return lines.join(\"\\n\");\n}\n\nexport interface AuditCoverageOptions {\n reporter?: \"pretty\" | \"json\";\n write?: boolean;\n}\n\n/** Commander action: run the audit over the repo's enrichment data. */\nexport function auditCoverageCommand(opts: AuditCoverageOptions = {}): void {\n const report = computeCoverage(loadFactions());\n\n if (opts.write) {\n mkdirSync(AUDIT_DIR, { recursive: true });\n writeFileSync(resolve(AUDIT_DIR, \"coverage.json\"), JSON.stringify(report, null, 2) + \"\\n\");\n writeFileSync(resolve(AUDIT_DIR, \"summary.md\"), markdownReport(report));\n // The named-gap worklist is the authoring artifact — split out so it's\n // diffable on its own and consumable without the histograms.\n writeFileSync(resolve(AUDIT_DIR, \"worklist.json\"), JSON.stringify(report.worklist, null, 2) + \"\\n\");\n }\n\n if (opts.reporter === \"json\") {\n console.log(JSON.stringify(report, null, 2));\n } else {\n console.log(prettyReport(report));\n if (opts.write) console.log(chalk.gray(`Wrote ${basename(AUDIT_DIR)}/coverage.json + summary.md`));\n }\n}\n\n// Direct-invocation entry point (`npx tsx tools/src/audit-coverage.ts [--json] [--write]`).\nconst isMain =\n process.argv[1] &&\n resolve(process.argv[1]).replace(/\\.\\w+$/, \"\") === fileURLToPath(import.meta.url).replace(/\\.\\w+$/, \"\");\nif (isMain) {\n const argv = process.argv.slice(2);\n auditCoverageCommand({\n reporter: argv.includes(\"--json\") ? \"json\" : \"pretty\",\n write: argv.includes(\"--write\"),\n });\n}\n"]}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
type Json = any;
|
|
2
|
+
export interface Proposal {
|
|
3
|
+
ability_id: string;
|
|
4
|
+
name: string;
|
|
5
|
+
faction: string;
|
|
6
|
+
effect_type?: string;
|
|
7
|
+
complex?: boolean;
|
|
8
|
+
confidence?: "high" | "medium" | "low";
|
|
9
|
+
schema_valid: boolean;
|
|
10
|
+
proposed_effect?: Json;
|
|
11
|
+
proposed_scope?: Json;
|
|
12
|
+
/** Ability-level behavior the repair pass inferred (passive/activated/reactive/aura). */
|
|
13
|
+
proposed_behavior?: string;
|
|
14
|
+
verdict?: {
|
|
15
|
+
severity: string;
|
|
16
|
+
faithful: boolean;
|
|
17
|
+
issue: string;
|
|
18
|
+
} | null;
|
|
19
|
+
final_faithful: boolean;
|
|
20
|
+
error?: string;
|
|
21
|
+
/** Set by the full-tree repair pass — the effect is a nested tree, not flat-form. */
|
|
22
|
+
repaired?: boolean;
|
|
23
|
+
/** Repair pass flagged this rule as genuinely unencodable (needs hand-authoring). */
|
|
24
|
+
unencodable?: boolean;
|
|
25
|
+
/** Canonical-key lint result (repair pass only). false = invented/out-of-vocab modifier keys. */
|
|
26
|
+
canonical?: boolean;
|
|
27
|
+
}
|
|
28
|
+
/** One batched, structured `claude -p` call. Resolves to the validated object. */
|
|
29
|
+
export declare function callClaude(system: string, user: string, schema: Json, model: string): Promise<Json>;
|
|
30
|
+
export declare const VERIFY_SYSTEM: string;
|
|
31
|
+
export declare const VERIFY_SCHEMA: {
|
|
32
|
+
type: string;
|
|
33
|
+
additionalProperties: boolean;
|
|
34
|
+
properties: {
|
|
35
|
+
results: {
|
|
36
|
+
type: string;
|
|
37
|
+
items: {
|
|
38
|
+
type: string;
|
|
39
|
+
additionalProperties: boolean;
|
|
40
|
+
properties: {
|
|
41
|
+
ability_id: {
|
|
42
|
+
type: string;
|
|
43
|
+
};
|
|
44
|
+
severity: {
|
|
45
|
+
enum: string[];
|
|
46
|
+
};
|
|
47
|
+
faithful: {
|
|
48
|
+
type: string;
|
|
49
|
+
};
|
|
50
|
+
issue: {
|
|
51
|
+
type: string;
|
|
52
|
+
};
|
|
53
|
+
};
|
|
54
|
+
required: string[];
|
|
55
|
+
};
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
required: string[];
|
|
59
|
+
};
|
|
60
|
+
export declare const REPAIR_SYSTEM: string;
|
|
61
|
+
export declare const REPAIR_SCHEMA: {
|
|
62
|
+
type: string;
|
|
63
|
+
additionalProperties: boolean;
|
|
64
|
+
properties: {
|
|
65
|
+
results: {
|
|
66
|
+
type: string;
|
|
67
|
+
items: {
|
|
68
|
+
type: string;
|
|
69
|
+
additionalProperties: boolean;
|
|
70
|
+
properties: {
|
|
71
|
+
ability_id: {
|
|
72
|
+
type: string;
|
|
73
|
+
};
|
|
74
|
+
effect: {
|
|
75
|
+
type: string;
|
|
76
|
+
additionalProperties: boolean;
|
|
77
|
+
};
|
|
78
|
+
scope: {
|
|
79
|
+
type: string;
|
|
80
|
+
additionalProperties: boolean;
|
|
81
|
+
};
|
|
82
|
+
behavior: {
|
|
83
|
+
type: string;
|
|
84
|
+
};
|
|
85
|
+
unencodable: {
|
|
86
|
+
type: string;
|
|
87
|
+
};
|
|
88
|
+
confidence: {
|
|
89
|
+
enum: string[];
|
|
90
|
+
};
|
|
91
|
+
reasoning: {
|
|
92
|
+
type: string;
|
|
93
|
+
};
|
|
94
|
+
};
|
|
95
|
+
required: string[];
|
|
96
|
+
};
|
|
97
|
+
};
|
|
98
|
+
};
|
|
99
|
+
required: string[];
|
|
100
|
+
};
|
|
101
|
+
export declare function conditionNode(kind: string, param: string | null | undefined): Json | null;
|
|
102
|
+
/** Build the effect node + scope from a flat-form. */
|
|
103
|
+
export declare function assembleEffect(form: Json): {
|
|
104
|
+
effect: Json;
|
|
105
|
+
scope: Json;
|
|
106
|
+
};
|
|
107
|
+
/** Splice the authored effect+scope onto the original entry, preserving metadata. */
|
|
108
|
+
export declare function buildEntry(original: Json, form: Json): Json;
|
|
109
|
+
/**
|
|
110
|
+
* Walk an effect tree and flag any cruncher-interpreted leaf whose modifier
|
|
111
|
+
* carries an unknown key or an out-of-vocabulary stat/roll/subset/attack_type.
|
|
112
|
+
* Non-interpreted leaf types (ability-grant, movement-modifier, …) are left
|
|
113
|
+
* permissive — they don't reach the damage path, so an unknown key there is a
|
|
114
|
+
* consistency nit, not a silent-corruption risk.
|
|
115
|
+
*/
|
|
116
|
+
export declare function lintCanonical(effect: Json): {
|
|
117
|
+
canonical: boolean;
|
|
118
|
+
issues: string[];
|
|
119
|
+
};
|
|
120
|
+
/**
|
|
121
|
+
* Splice a pre-formed nested effect tree (from the repair pass) onto the original
|
|
122
|
+
* entry. Unlike {@link buildEntry} the LLM owns the whole tree, so we only graft
|
|
123
|
+
* `effect`/`scope`/`behavior` and the citation — never the flat-form assembly.
|
|
124
|
+
* `behavior` is an ability-level field; only set it when the model returned a
|
|
125
|
+
* valid enum value (an invalid one would just fail AJV and lose the whole entry).
|
|
126
|
+
*/
|
|
127
|
+
export declare function buildRepairedEntry(original: Json, effect: Json, scope: Json, behavior?: string): Json;
|
|
128
|
+
export interface GateOpts {
|
|
129
|
+
minConfidence: "high" | "medium";
|
|
130
|
+
includeComplex: boolean;
|
|
131
|
+
}
|
|
132
|
+
/** Whether a proposal is safe to apply automatically. */
|
|
133
|
+
export declare function passesGate(p: Proposal, opts: GateOpts): boolean;
|
|
134
|
+
export declare const verifyUserPrompt: (entries: {
|
|
135
|
+
ability_id: string;
|
|
136
|
+
rule: string;
|
|
137
|
+
effect: Json;
|
|
138
|
+
scope: Json;
|
|
139
|
+
}[]) => string;
|
|
140
|
+
export declare const repairUserPrompt: (items: {
|
|
141
|
+
ability_id: string;
|
|
142
|
+
rule: string;
|
|
143
|
+
draft: Json;
|
|
144
|
+
issue: string;
|
|
145
|
+
}[]) => string;
|
|
146
|
+
export {};
|
|
147
|
+
//# sourceMappingURL=author-batch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"author-batch.d.ts","sourceRoot":"","sources":["../src/author-batch.ts"],"names":[],"mappings":"AA8CA,KAAK,IAAI,GAAG,GAAG,CAAC;AAMhB,MAAM,WAAW,QAAQ;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;IACvC,YAAY,EAAE,OAAO,CAAC;IACtB,eAAe,CAAC,EAAE,IAAI,CAAC;IACvB,cAAc,CAAC,EAAE,IAAI,CAAC;IACtB,yFAAyF;IACzF,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,OAAO,CAAC,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,OAAO,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACxE,cAAc,EAAE,OAAO,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,qFAAqF;IACrF,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,qFAAqF;IACrF,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,iGAAiG;IACjG,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAID,kFAAkF;AAClF,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAoBnG;AA0BD,eAAO,MAAM,aAAa,QAGqL,CAAC;AAkBhN,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAQzB,CAAC;AAaF,eAAO,MAAM,aAAa,QA4Bsb,CAAC;AAEjd,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgBzB,CAAC;AAIF,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,IAAI,GAAG,IAAI,CAYzF;AAED,sDAAsD;AACtD,wBAAgB,cAAc,CAAC,IAAI,EAAE,IAAI,GAAG;IAAE,MAAM,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,IAAI,CAAA;CAAE,CASxE;AAED,qFAAqF;AACrF,wBAAgB,UAAU,CAAC,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,GAAG,IAAI,CAG3D;AAsCD;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,IAAI,GAAG;IAAE,SAAS,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAiCpF;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAIrG;AAID,MAAM,WAAW,QAAQ;IAAG,aAAa,EAAE,MAAM,GAAG,QAAQ,CAAC;IAAC,cAAc,EAAE,OAAO,CAAA;CAAE;AAEvF,yDAAyD;AACzD,wBAAgB,UAAU,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,GAAG,OAAO,CAY/D;AAcD,eAAO,MAAM,gBAAgB,GAAI,SAAS;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,IAAI,CAAA;CAAE,EAAE,KAAG,MAE0C,CAAC;AAEzJ,eAAO,MAAM,gBAAgB,GAAI,OAAO;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,EAAE,KAAG,MAI7F,CAAC"}
|