New:Socket for Asana Is Now Available.Learn more
Get Started

@archstone/init

Package Overview
Dependencies
Maintainers
1
Versions
19
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@archstone/init - npm Package Compare versions

Comparing version
0.14.0
to
0.15.0
+1
-1
dist/loop.js

@@ -80,3 +80,3 @@ import {

async function verifyRecorded(ir, dir, opts) {
const reports = await runVerify(ir.tools, dir, ir.resources, opts);
const { results: reports } = await runVerify(ir.tools, dir, ir.resources, opts);
const green = new Set(reports.filter((r) => r.status !== "red").map((r) => r.capabilityId));

@@ -83,0 +83,0 @@ return { green, reports: reports.map((r) => ({ capabilityId: r.capabilityId, status: r.status, detail: r.detail })) };

@@ -1,1 +0,1 @@

{"version":3,"sources":["../src/loop.ts","../src/probe.ts"],"sourcesContent":["// @archstone/init/loop — the closed loop (ADD-37 §6 step 3).\n//\n// THE PRODUCT IS THE LOOP, NOT THE GENERATOR. Generation alone loses to \"paste your spec into\n// an assistant and ask for CDL\"; generation that the REAL compiler immediately compiles does\n// not. So this module's whole job is to stand between the emitted bytes and the developer's\n// directory, and to have exactly two terminal states (D-7):\n//\n// a compiling manifest was written | nothing was written, and here is why\n//\n// There is no \"mostly works, fix the errors yourself\" mode. That is an invariant with a test,\n// not a quality goal — a tool that writes files it cannot defend is the thing the integrating\n// developer is most afraid of (product §2).\n//\n// WHY A TEMP DIRECTORY (O-8): `load()` is fs-only — there is no in-memory entry point — and\n// this increment deliberately does NOT refactor it for one caller's convenience. The emitted\n// file set is materialized to a temp dir, compiled there, and only COPIED FROM THERE on\n// success, so the bytes that land in the target are byte-for-byte the bytes that compiled.\n//\n// This is the only module in the package that touches a filesystem. The root export\n// (`@archstone/init`) is pure and stays that way; that split is what lets a hosted flow reuse\n// the inference core verbatim (§9's forward constraint).\n\nimport { cpSync, existsSync, mkdirSync, mkdtempSync, readdirSync, rmSync, statSync, writeFileSync } from \"node:fs\";\nimport { dirname, isAbsolute, join, normalize, resolve, sep } from \"node:path\";\nimport { tmpdir } from \"node:os\";\nimport { load, type LoadIssue } from \"@archstone/schema\";\nimport { compile, validateSemantics, type IR } from \"@archstone/compiler\";\nimport { Registry } from \"@archstone/emitter-support\";\nimport type { RecordContractOptions } from \"@archstone/runtime/verify\";\nimport { emit, type EmitResult, type RecordedContract } from \"./emit\";\nimport { keptDecisions, type DecisionRecord } from \"./decisions\";\nimport type { DraftModel } from \"./model\";\nimport { runProbes, verifyRecorded, type ProbeReport } from \"./probe\";\n\n/**\n * Why nothing was written.\n *\n * A SEPARATE vocabulary from `ReasonCode` (reasons.ts) on purpose: a skip is per-candidate and\n * informational — the run still succeeds — while every code here is terminal for the whole\n * manifest. One shared enum would let those two very different states share a word.\n */\nexport type LoopFailureCode =\n /** The emitter produced no files at all (e.g. an empty confirmed set). Already a refusal\n * upstream; re-checked here because this module must never write an empty manifest. */\n | \"empty-file-set\"\n /** A relative path escaping the target directory. Never expected from the shipped emitter —\n * present because this function writes to a path a caller supplied. */\n | \"unsafe-path\"\n /** `load()` rejected a shape. */\n | \"shape-invalid\"\n /** `validateSemantics` reported an error (an unresolvable resource, an unknown provider). */\n | \"semantic-error\"\n /** Two capability ids sanitize to the same advertised tool name. `apply` and `build` both\n * refuse such a manifest (ADD-30 D-2); `init` must refuse the identical one, or it becomes\n * the one tool in the toolchain that writes something the rest will not accept. */\n | \"tool-name-collision\"\n /** The target directory already has content and `--force` was not given. */\n | \"target-not-empty\"\n /** The filesystem refused. */\n | \"write-failed\";\n\nexport interface LoopFailure {\n code: LoopFailureCode;\n message: string;\n /** The manifest file the failure is about, when it is about one. */\n file?: string;\n}\n\nexport interface LoopResult {\n ok: boolean;\n /** Absolute paths written. ALWAYS empty when `ok` is false — there is no partial write. */\n written: string[];\n failures: LoopFailure[];\n /** The compiled IR of the manifest that was written. Present only on success — the harness\n * and the report both read it, and neither should ever see a half-compiled one. */\n ir?: IR;\n}\n\nexport interface CommitOptions {\n /** Where the manifest should end up. Created if missing. */\n targetDir: string;\n /** Write into a non-empty target. The only escape from \"strictly fresh\". */\n force?: boolean;\n /** Parent for the temp directory. Defaults to the OS temp dir. */\n tmpRoot?: string;\n}\n\n/** Reject anything that would escape the directory it is written into. */\nfunction isSafeRelativePath(path: string): boolean {\n if (path === \"\" || isAbsolute(path)) return false;\n const normalized = normalize(path);\n return !normalized.startsWith(`..${sep}`) && normalized !== \"..\" && !normalized.split(/[\\\\/]/).includes(\"..\");\n}\n\nfunction writeFileSet(dir: string, files: ReadonlyMap<string, string>): void {\n for (const [relative, content] of files) {\n const target = join(dir, relative);\n mkdirSync(dirname(target), { recursive: true });\n writeFileSync(target, content);\n }\n}\n\nfunction isNonEmptyDirectory(path: string): boolean {\n if (!existsSync(path)) return false;\n const stat = statSync(path);\n if (!stat.isDirectory()) return true; // a FILE at the target path is certainly \"not empty\"\n return readdirSync(path).length > 0;\n}\n\n/**\n * Compile a manifest directory exactly the way the rest of the toolchain does — `load` →\n * `validateSemantics` → `compile` → `new Registry()` — and report the first stage that\n * refused.\n *\n * The tool-name-collision check reads `Registry.toolNameCollisions`, the same computed value\n * `apply`, `build` and `serve` all gate on, rather than re-deriving \"which ids sanitize to the\n * same name\" here. Two implementations of that question is exactly the drift the shared\n * registry exists to remove.\n */\nexport function compileManifest(dir: string): { ok: boolean; ir?: IR; failures: LoopFailure[]; issues: LoadIssue[] } {\n const failures: LoopFailure[] = [];\n const model = load(dir);\n for (const issue of model.issues) {\n failures.push({ code: \"shape-invalid\", message: issue.message, file: issue.file });\n }\n\n const diagnostics = validateSemantics(model);\n for (const d of diagnostics) {\n if (d.severity === \"error\") failures.push({ code: \"semantic-error\", message: d.message });\n }\n\n if (failures.length > 0) return { ok: false, failures, issues: model.issues };\n\n const ir = compile(model);\n const registry = new Registry(ir);\n for (const collision of registry.toolNameCollisions) {\n failures.push({\n code: \"tool-name-collision\",\n message: `tool name '${collision.name}' is ambiguous — capabilities ${collision.ids.join(\", \")} all sanitize to it`,\n });\n }\n if (failures.length > 0) return { ok: false, failures, issues: model.issues };\n\n return { ok: true, ir, failures, issues: model.issues };\n}\n\n/**\n * Materialize an emitted file set, compile it, and commit it to the target ONLY if it compiled.\n *\n * On any failure the temp directory is removed and the target is left exactly as it was —\n * including \"does not exist\". A caller can therefore treat `ok === false` as \"the developer's\n * directory is untouched\", with no cleanup of its own.\n */\nexport function commitFileSet(files: ReadonlyMap<string, string>, opts: CommitOptions): LoopResult {\n const failures: LoopFailure[] = [];\n\n if (files.size === 0) {\n return { ok: false, written: [], failures: [{ code: \"empty-file-set\", message: \"nothing to write\" }] };\n }\n for (const relative of files.keys()) {\n if (!isSafeRelativePath(relative)) {\n failures.push({ code: \"unsafe-path\", message: `refusing to write outside the target directory`, file: relative });\n }\n }\n if (failures.length > 0) return { ok: false, written: [], failures };\n\n const target = resolve(opts.targetDir);\n if (isNonEmptyDirectory(target) && opts.force !== true) {\n return {\n ok: false,\n written: [],\n failures: [{ code: \"target-not-empty\", message: `${target} is not empty — re-run with force to overwrite` }],\n };\n }\n\n const temp = mkdtempSync(join(opts.tmpRoot ?? tmpdir(), \"archstone-init-\"));\n try {\n try {\n // FORCE MERGES, and a merge is not what was compiled unless it is compiled.\n //\n // Committing into a non-empty target leaves behind whatever the previous run wrote and\n // this one does not — a capability file for a candidate the human has since declined, a\n // resource nothing references any more. Those files are still `load()`ed, so the manifest\n // that ends up on disk is the UNION, and validating only the emitted half would report\n // \"a compiling manifest was written\" about a directory that does not compile (verified:\n // a stale capability referencing a deleted resource does exactly this).\n //\n // So the temp dir is seeded with the target's current contents and the emitted files are\n // overlaid on top: what gets compiled below is byte-for-byte what the target will become.\n // If the union does not compile, nothing is written and the developer is told which\n // leftover file broke it.\n if (opts.force === true && existsSync(target) && statSync(target).isDirectory()) {\n cpSync(target, temp, { recursive: true });\n }\n writeFileSet(temp, files);\n } catch (err) {\n return { ok: false, written: [], failures: [{ code: \"write-failed\", message: (err as Error).message }] };\n }\n\n const compiled = compileManifest(temp);\n if (!compiled.ok || !compiled.ir) {\n return { ok: false, written: [], failures: compiled.failures };\n }\n\n // Commit: copy the VALIDATED bytes out of the temp dir, never re-render them.\n try {\n mkdirSync(target, { recursive: true });\n cpSync(temp, target, { recursive: true, force: true });\n } catch (err) {\n return { ok: false, written: [], failures: [{ code: \"write-failed\", message: (err as Error).message }] };\n }\n\n return { ok: true, written: [...files.keys()].map((relative) => join(target, relative)).sort(), failures: [], ir: compiled.ir };\n } finally {\n rmSync(temp, { recursive: true, force: true });\n }\n}\n\n/** Compile two manifest directories and diff their IRs — the fs-facing half of the harness.\n * The comparison itself is pure and lives in the root export (`diffIR`). */\nexport function compileForDiff(dir: string): IR {\n const compiled = compileManifest(dir);\n if (!compiled.ok || !compiled.ir) {\n const detail = compiled.failures.map((f) => `${f.file ? `${f.file}: ` : \"\"}${f.message}`).join(\"; \");\n throw new Error(`cannot compile '${dir}' for comparison — ${detail}`);\n }\n return compiled.ir;\n}\n\n// ---------------------------------------------------------------------------------------\n// The whole loop, including the probe leg (ADD-37 §6 step 6)\n// ---------------------------------------------------------------------------------------\n\nexport interface RunInitOptions extends CommitOptions {\n /** The `--probe` opt-in. Absent/false ⇒ NO request is made, under any circumstances, for\n * any capability, whatever the Decision Record says. Opt-in at the top level, then gated\n * again per capability (R-8). */\n probe?: boolean;\n /** False for CI and for a Decision Record file. Governs only the non-`GET`/`HEAD` second\n * confirmation, which is a human act. */\n interactive?: boolean;\n /** Threaded to `invokeRest` for env resolution and, in tests, a stub fetch. */\n invoke?: RecordContractOptions;\n}\n\nexport interface InitResult extends LoopResult {\n emitted: EmitResult;\n /** One entry per kept decision when probing, empty otherwise. */\n probes: ProbeReport[];\n /** What the real `runVerify` said about the contracts that were written. */\n verifications: { capabilityId: string; status: string; detail: string }[];\n}\n\n/**\n * Draft Model + Decision Record → a compiling manifest on disk, or nothing at all.\n *\n * The sequence, and why it is this shape:\n *\n * 1. emit WITHOUT contracts, materialize, compile. The probe needs a compiled `IRTool` — it\n * calls the backend the way the manifest says to, not the way the draft implies.\n * 2. probe (gated per capability), producing recordings.\n * 3. re-emit WITH the recordings, materialize again, compile again, and run the REAL\n * `runVerify` over that directory. A contract that cannot be replayed is dropped here,\n * before anything reaches the developer.\n * 4. emit a final time with only the surviving contracts, and commit.\n *\n * Three materializations rather than one, deliberately: each stage compiles the exact bytes\n * the next stage acts on, so \"a compiling manifest was written\" is never inferred from a\n * different set of bytes than the ones that landed.\n */\nexport async function runInit(draft: DraftModel, record: DecisionRecord, opts: RunInitOptions): Promise<InitResult> {\n const kept = keptDecisions(record);\n const emptyResult = (emitted: EmitResult, failures: LoopFailure[]): InitResult => ({\n ok: false,\n written: [],\n failures,\n emitted,\n probes: [],\n verifications: [],\n });\n\n const firstPass = emit(draft, record);\n if (firstPass.files.size === 0) {\n // D-7's manifest-level refusal, already decided by the emitter (an empty confirmed set, an\n // invalid company id). Nothing is written and the notes say why.\n return emptyResult(firstPass, [{ code: \"empty-file-set\", message: \"the emitter refused — see the report's notes\" }]);\n }\n\n if (opts.probe !== true) {\n const committed = commitFileSet(firstPass.files, opts);\n return { ...committed, emitted: firstPass, probes: [], verifications: [] };\n }\n\n const staging = mkdtempSync(join(opts.tmpRoot ?? tmpdir(), \"archstone-init-probe-\"));\n try {\n writeFileSet(staging, firstPass.files);\n const compiled = compileManifest(staging);\n if (!compiled.ok || !compiled.ir) return emptyResult(firstPass, compiled.failures);\n\n const probes = await runProbes(compiled.ir, kept, { ...opts.invoke, interactive: opts.interactive === true });\n\n const recorded = new Map<string, RecordedContract>();\n for (const probe of probes) if (probe.contract) recorded.set(probe.capabilityId, probe.contract);\n\n if (recorded.size === 0) {\n const committed = commitFileSet(firstPass.files, opts);\n return { ...committed, emitted: firstPass, probes, verifications: [] };\n }\n\n // Re-emit with the recordings and REPLAY them, in a second staging directory, before any\n // of it is offered to the developer (R-1).\n const replayDir = mkdtempSync(join(opts.tmpRoot ?? tmpdir(), \"archstone-init-replay-\"));\n try {\n const withContracts = emit(draft, record, recorded);\n writeFileSet(replayDir, withContracts.files);\n const recompiled = compileManifest(replayDir);\n if (!recompiled.ok || !recompiled.ir) return emptyResult(withContracts, recompiled.failures);\n\n const { green, reports } = await verifyRecorded(recompiled.ir, replayDir, opts.invoke);\n const survivors = new Map([...recorded].filter(([id]) => green.has(id)));\n\n // A contract that recorded green and then failed its own replay is dropped, not shipped.\n // The manifest still lands; only the safety net that could not be trusted is withheld.\n const finalPass = survivors.size === recorded.size ? withContracts : emit(draft, record, survivors);\n const committed = commitFileSet(finalPass.files, opts);\n return { ...committed, emitted: finalPass, probes, verifications: reports };\n } finally {\n rmSync(replayDir, { recursive: true, force: true });\n }\n } finally {\n rmSync(staging, { recursive: true, force: true });\n }\n}\n","// @archstone/init — the probe leg (ADD-37 §6 step 6, D-6, R-1, R-8).\n//\n// THE ONE FAILURE THE BUSINESS OWNER ACTUALLY FEARS is that a scaffolding tool pointed at\n// their production API writes something. So the gate below has two independent conditions and\n// both are required, and neither of them lives in this file's callee:\n//\n// 1. a CONFIRMED `effect: read` — a human said so, at a gate, per capability; and\n// 2. the METHOD rule — `GET`/`HEAD` ride on that confirmation alone, anything else needs a\n// SECOND, separate explicit confirmation, and in non-interactive mode a non-`GET`/`HEAD`\n// probe is refused outright, with no flag that enables one.\n//\n// `GET`-only would be the wrong gate and is worth saying why: `tourism.search` is a\n// `POST /v1/search` with `effect: read`, the canonical search shape. The method rule is a\n// second condition ON TOP of the confirmed read, never a substitute for it.\n//\n// This module lives in the `/loop` entry, not the root: it reaches the network (through\n// `@archstone/runtime/verify`, never through an HTTP client of its own) and the root export is\n// pure. `init` opens no socket — it asks the module that already owns record-and-replay to do\n// it, so the fixture written here is by construction the artifact `verify` will replay (R-1).\n\nimport { recordContract, runVerify, type ContractRecording, type ProbeOutcome, type RecordContractOptions } from \"@archstone/runtime/verify\";\nimport type { IR, IRTool } from \"@archstone/compiler\";\nimport type { CapabilityDecision } from \"./decisions\";\nimport type { RecordedContract } from \"./emit\";\n\n/** Why a probe did not happen. Distinct from `ProbeOutcome`, which is why one that DID happen\n * ended the way it did — conflating them would let \"we chose not to call\" and \"we called and\n * it failed\" share a word, and those are opposite facts about a backend. */\nexport type ProbeRefusal =\n /** The human did not consent. The default, and the common case. */\n | \"no-consent\"\n /** The confirmed effect is not `read`. No flag overrides this. */\n | \"effect-not-read\"\n /** A non-`GET`/`HEAD` method with no second explicit confirmation. */\n | \"method-not-confirmed\"\n /** A non-`GET`/`HEAD` method in non-interactive mode. Refused outright — there is\n * deliberately no flag, because the second confirmation is a HUMAN act and CI has no human. */\n | \"non-interactive-non-read-method\"\n /** §1.3: the fixture's `request` is capability input, and none was supplied. */\n | \"probe-input-unavailable\"\n /** The compiled manifest has no such tool, or the tool has no connector to call. */\n | \"not-invocable\";\n\nexport interface ProbeReport {\n capabilityId: string;\n /** `refused` means no request was issued. Everything else is an outcome of a real attempt —\n * except `not-attempted`, which means `invokeRest` declined to send one. */\n outcome: ProbeOutcome | \"refused\";\n refusal?: ProbeRefusal;\n detail: string;\n /** Present iff the recording survived a real `runVerify` replay. */\n contract?: RecordedContract;\n degraded?: string[];\n missing?: string[];\n}\n\nconst FREE_METHODS = new Set([\"GET\", \"HEAD\"]);\n\nexport interface GateContext {\n /** False for CI and for a Decision Record file. The distinction is not cosmetic: the\n * non-`GET` second confirmation is a human act, and there is no human here. */\n interactive: boolean;\n}\n\nexport type GateResult = { allowed: true; input: Record<string, unknown> } | { allowed: false; refusal: ProbeRefusal; detail: string };\n\n/**\n * R-8's gate, as a pure function so it can be tested exhaustively without a backend.\n *\n * Every refusal path returns BEFORE any caller could reach `recordContract`, and the tests\n * assert the strong form of that — \"no request is issued for any non-confirmed-read\n * capability, under any flag\" — by counting calls to an injected fetch, not by inspecting\n * this function's return value.\n */\nexport function probeGate(decision: Extract<CapabilityDecision, { keep: true }>, tool: IRTool | undefined, ctx: GateContext): GateResult {\n if (!tool || !tool.connector) {\n return { allowed: false, refusal: \"not-invocable\", detail: \"the compiled manifest has no invocable tool for this capability\" };\n }\n if (decision.probe !== true) {\n return { allowed: false, refusal: \"no-consent\", detail: \"no probe was requested for this capability\" };\n }\n if (decision.effect !== \"read\") {\n return { allowed: false, refusal: \"effect-not-read\", detail: `confirmed effect is '${decision.effect}' — \\`init\\` never issues a write` };\n }\n\n const method = (tool.connector.rest?.method ?? \"\").toUpperCase();\n if (!FREE_METHODS.has(method)) {\n if (!ctx.interactive) {\n return {\n allowed: false,\n refusal: \"non-interactive-non-read-method\",\n detail: `${method} needs a second, explicit human confirmation, and there is no human here`,\n };\n }\n if (decision.probeNonReadMethodConfirmed !== true) {\n return { allowed: false, refusal: \"method-not-confirmed\", detail: `${method} needs a second, separate confirmation beyond \\`effect: read\\`` };\n }\n }\n\n const input = decision.sampleInput;\n const missing = tool.input.filter((f) => f.required && (input === undefined || input[f.name] === undefined)).map((f) => f.name);\n if (missing.length > 0) {\n // §1.3, and the sharpest unglamorous constraint in the increment: the fixture's `request`\n // is CAPABILITY input, not an HTTP request, and a document usually cannot supply it. A\n // report line, never a fallback — and never the adapter's `example`, which may name a real\n // customer's record (D-13).\n return { allowed: false, refusal: \"probe-input-unavailable\", detail: `no sample value for required input(s): ${missing.join(\", \")}` };\n }\n return { allowed: true, input: input ?? {} };\n}\n\n/** A recording promoted to an emittable contract — or `undefined` when nothing may be written. */\nfunction contractOf(recording: ContractRecording): RecordedContract | undefined {\n if (recording.fingerprint === undefined || recording.fixture === undefined) return undefined;\n return {\n fingerprint: recording.fingerprint,\n ...(recording.shape ? { shape: recording.shape } : {}),\n recordedAt: recording.fixture.recordedAt ?? new Date(0).toISOString(),\n fixture: recording.fixture,\n };\n}\n\nexport interface RunProbesOptions extends RecordContractOptions {\n interactive: boolean;\n}\n\n/**\n * Probe every consented capability against the compiled manifest, once.\n *\n * Returns reports only — writing is the caller's job, and keeping it that way is what lets the\n * loop drop a contract after a failed replay without this function knowing about files.\n */\nexport async function runProbes(\n ir: IR,\n decisions: Extract<CapabilityDecision, { keep: true }>[],\n opts: RunProbesOptions,\n): Promise<ProbeReport[]> {\n const byId = new Map(ir.tools.map((t) => [t.id, t]));\n const reports: ProbeReport[] = [];\n\n // Sequential, not `Promise.all`: these are live calls to somebody's production backend, made\n // by a scaffolding tool the user is running for the first time. A burst is a worse first\n // impression than a wait, and nothing here is latency-sensitive.\n for (const decision of decisions) {\n const tool = byId.get(decision.capabilityId);\n const gate = probeGate(decision, tool, { interactive: opts.interactive });\n if (!gate.allowed) {\n reports.push({ capabilityId: decision.capabilityId, outcome: \"refused\", refusal: gate.refusal, detail: gate.detail });\n continue;\n }\n const recording = await recordContract(tool!, gate.input, ir.resources, opts);\n const contract = contractOf(recording);\n reports.push({\n capabilityId: decision.capabilityId,\n outcome: recording.outcome,\n detail: recording.detail,\n ...(contract ? { contract } : {}),\n ...(recording.degraded ? { degraded: recording.degraded } : {}),\n ...(recording.missing ? { missing: recording.missing } : {}),\n });\n }\n return reports;\n}\n\n/**\n * R-1's mitigation, made real: replay every just-written contract through the SHIPPED\n * `runVerify`, over the directory the files were written into, and report which ones survived.\n *\n * Not belt-and-braces. `recordContract` and `verifyTool` share a module and an `invokeRest`\n * call, which is what makes the artifact replayable in principle; this proves it in fact, on\n * this manifest, against this backend, before the developer's directory is touched. A fixture\n * that looks green at record time and cannot be replayed afterwards turns the safety net into\n * a liability, silently, for the manifest's lifetime.\n */\nexport async function verifyRecorded(\n ir: IR,\n dir: string,\n opts?: RecordContractOptions,\n): Promise<{ green: Set<string>; reports: { capabilityId: string; status: string; detail: string }[] }> {\n const reports = await runVerify(ir.tools, dir, ir.resources, opts);\n const green = new Set(reports.filter((r) => r.status !== \"red\").map((r) => r.capabilityId));\n return { green, reports: reports.map((r) => ({ capabilityId: r.capabilityId, status: r.status, detail: r.detail })) };\n}\n"],"mappings":"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","names":[]}
{"version":3,"sources":["../src/loop.ts","../src/probe.ts"],"sourcesContent":["// @archstone/init/loop — the closed loop (ADD-37 §6 step 3).\n//\n// THE PRODUCT IS THE LOOP, NOT THE GENERATOR. Generation alone loses to \"paste your spec into\n// an assistant and ask for CDL\"; generation that the REAL compiler immediately compiles does\n// not. So this module's whole job is to stand between the emitted bytes and the developer's\n// directory, and to have exactly two terminal states (D-7):\n//\n// a compiling manifest was written | nothing was written, and here is why\n//\n// There is no \"mostly works, fix the errors yourself\" mode. That is an invariant with a test,\n// not a quality goal — a tool that writes files it cannot defend is the thing the integrating\n// developer is most afraid of (product §2).\n//\n// WHY A TEMP DIRECTORY (O-8): `load()` is fs-only — there is no in-memory entry point — and\n// this increment deliberately does NOT refactor it for one caller's convenience. The emitted\n// file set is materialized to a temp dir, compiled there, and only COPIED FROM THERE on\n// success, so the bytes that land in the target are byte-for-byte the bytes that compiled.\n//\n// This is the only module in the package that touches a filesystem. The root export\n// (`@archstone/init`) is pure and stays that way; that split is what lets a hosted flow reuse\n// the inference core verbatim (§9's forward constraint).\n\nimport { cpSync, existsSync, mkdirSync, mkdtempSync, readdirSync, rmSync, statSync, writeFileSync } from \"node:fs\";\nimport { dirname, isAbsolute, join, normalize, resolve, sep } from \"node:path\";\nimport { tmpdir } from \"node:os\";\nimport { load, type LoadIssue } from \"@archstone/schema\";\nimport { compile, validateSemantics, type IR } from \"@archstone/compiler\";\nimport { Registry } from \"@archstone/emitter-support\";\nimport type { RecordContractOptions } from \"@archstone/runtime/verify\";\nimport { emit, type EmitResult, type RecordedContract } from \"./emit\";\nimport { keptDecisions, type DecisionRecord } from \"./decisions\";\nimport type { DraftModel } from \"./model\";\nimport { runProbes, verifyRecorded, type ProbeReport } from \"./probe\";\n\n/**\n * Why nothing was written.\n *\n * A SEPARATE vocabulary from `ReasonCode` (reasons.ts) on purpose: a skip is per-candidate and\n * informational — the run still succeeds — while every code here is terminal for the whole\n * manifest. One shared enum would let those two very different states share a word.\n */\nexport type LoopFailureCode =\n /** The emitter produced no files at all (e.g. an empty confirmed set). Already a refusal\n * upstream; re-checked here because this module must never write an empty manifest. */\n | \"empty-file-set\"\n /** A relative path escaping the target directory. Never expected from the shipped emitter —\n * present because this function writes to a path a caller supplied. */\n | \"unsafe-path\"\n /** `load()` rejected a shape. */\n | \"shape-invalid\"\n /** `validateSemantics` reported an error (an unresolvable resource, an unknown provider). */\n | \"semantic-error\"\n /** Two capability ids sanitize to the same advertised tool name. `apply` and `build` both\n * refuse such a manifest (ADD-30 D-2); `init` must refuse the identical one, or it becomes\n * the one tool in the toolchain that writes something the rest will not accept. */\n | \"tool-name-collision\"\n /** The target directory already has content and `--force` was not given. */\n | \"target-not-empty\"\n /** The filesystem refused. */\n | \"write-failed\";\n\nexport interface LoopFailure {\n code: LoopFailureCode;\n message: string;\n /** The manifest file the failure is about, when it is about one. */\n file?: string;\n}\n\nexport interface LoopResult {\n ok: boolean;\n /** Absolute paths written. ALWAYS empty when `ok` is false — there is no partial write. */\n written: string[];\n failures: LoopFailure[];\n /** The compiled IR of the manifest that was written. Present only on success — the harness\n * and the report both read it, and neither should ever see a half-compiled one. */\n ir?: IR;\n}\n\nexport interface CommitOptions {\n /** Where the manifest should end up. Created if missing. */\n targetDir: string;\n /** Write into a non-empty target. The only escape from \"strictly fresh\". */\n force?: boolean;\n /** Parent for the temp directory. Defaults to the OS temp dir. */\n tmpRoot?: string;\n}\n\n/** Reject anything that would escape the directory it is written into. */\nfunction isSafeRelativePath(path: string): boolean {\n if (path === \"\" || isAbsolute(path)) return false;\n const normalized = normalize(path);\n return !normalized.startsWith(`..${sep}`) && normalized !== \"..\" && !normalized.split(/[\\\\/]/).includes(\"..\");\n}\n\nfunction writeFileSet(dir: string, files: ReadonlyMap<string, string>): void {\n for (const [relative, content] of files) {\n const target = join(dir, relative);\n mkdirSync(dirname(target), { recursive: true });\n writeFileSync(target, content);\n }\n}\n\nfunction isNonEmptyDirectory(path: string): boolean {\n if (!existsSync(path)) return false;\n const stat = statSync(path);\n if (!stat.isDirectory()) return true; // a FILE at the target path is certainly \"not empty\"\n return readdirSync(path).length > 0;\n}\n\n/**\n * Compile a manifest directory exactly the way the rest of the toolchain does — `load` →\n * `validateSemantics` → `compile` → `new Registry()` — and report the first stage that\n * refused.\n *\n * The tool-name-collision check reads `Registry.toolNameCollisions`, the same computed value\n * `apply`, `build` and `serve` all gate on, rather than re-deriving \"which ids sanitize to the\n * same name\" here. Two implementations of that question is exactly the drift the shared\n * registry exists to remove.\n */\nexport function compileManifest(dir: string): { ok: boolean; ir?: IR; failures: LoopFailure[]; issues: LoadIssue[] } {\n const failures: LoopFailure[] = [];\n const model = load(dir);\n for (const issue of model.issues) {\n failures.push({ code: \"shape-invalid\", message: issue.message, file: issue.file });\n }\n\n const diagnostics = validateSemantics(model);\n for (const d of diagnostics) {\n if (d.severity === \"error\") failures.push({ code: \"semantic-error\", message: d.message });\n }\n\n if (failures.length > 0) return { ok: false, failures, issues: model.issues };\n\n const ir = compile(model);\n const registry = new Registry(ir);\n for (const collision of registry.toolNameCollisions) {\n failures.push({\n code: \"tool-name-collision\",\n message: `tool name '${collision.name}' is ambiguous — capabilities ${collision.ids.join(\", \")} all sanitize to it`,\n });\n }\n if (failures.length > 0) return { ok: false, failures, issues: model.issues };\n\n return { ok: true, ir, failures, issues: model.issues };\n}\n\n/**\n * Materialize an emitted file set, compile it, and commit it to the target ONLY if it compiled.\n *\n * On any failure the temp directory is removed and the target is left exactly as it was —\n * including \"does not exist\". A caller can therefore treat `ok === false` as \"the developer's\n * directory is untouched\", with no cleanup of its own.\n */\nexport function commitFileSet(files: ReadonlyMap<string, string>, opts: CommitOptions): LoopResult {\n const failures: LoopFailure[] = [];\n\n if (files.size === 0) {\n return { ok: false, written: [], failures: [{ code: \"empty-file-set\", message: \"nothing to write\" }] };\n }\n for (const relative of files.keys()) {\n if (!isSafeRelativePath(relative)) {\n failures.push({ code: \"unsafe-path\", message: `refusing to write outside the target directory`, file: relative });\n }\n }\n if (failures.length > 0) return { ok: false, written: [], failures };\n\n const target = resolve(opts.targetDir);\n if (isNonEmptyDirectory(target) && opts.force !== true) {\n return {\n ok: false,\n written: [],\n failures: [{ code: \"target-not-empty\", message: `${target} is not empty — re-run with force to overwrite` }],\n };\n }\n\n const temp = mkdtempSync(join(opts.tmpRoot ?? tmpdir(), \"archstone-init-\"));\n try {\n try {\n // FORCE MERGES, and a merge is not what was compiled unless it is compiled.\n //\n // Committing into a non-empty target leaves behind whatever the previous run wrote and\n // this one does not — a capability file for a candidate the human has since declined, a\n // resource nothing references any more. Those files are still `load()`ed, so the manifest\n // that ends up on disk is the UNION, and validating only the emitted half would report\n // \"a compiling manifest was written\" about a directory that does not compile (verified:\n // a stale capability referencing a deleted resource does exactly this).\n //\n // So the temp dir is seeded with the target's current contents and the emitted files are\n // overlaid on top: what gets compiled below is byte-for-byte what the target will become.\n // If the union does not compile, nothing is written and the developer is told which\n // leftover file broke it.\n if (opts.force === true && existsSync(target) && statSync(target).isDirectory()) {\n cpSync(target, temp, { recursive: true });\n }\n writeFileSet(temp, files);\n } catch (err) {\n return { ok: false, written: [], failures: [{ code: \"write-failed\", message: (err as Error).message }] };\n }\n\n const compiled = compileManifest(temp);\n if (!compiled.ok || !compiled.ir) {\n return { ok: false, written: [], failures: compiled.failures };\n }\n\n // Commit: copy the VALIDATED bytes out of the temp dir, never re-render them.\n try {\n mkdirSync(target, { recursive: true });\n cpSync(temp, target, { recursive: true, force: true });\n } catch (err) {\n return { ok: false, written: [], failures: [{ code: \"write-failed\", message: (err as Error).message }] };\n }\n\n return { ok: true, written: [...files.keys()].map((relative) => join(target, relative)).sort(), failures: [], ir: compiled.ir };\n } finally {\n rmSync(temp, { recursive: true, force: true });\n }\n}\n\n/** Compile two manifest directories and diff their IRs — the fs-facing half of the harness.\n * The comparison itself is pure and lives in the root export (`diffIR`). */\nexport function compileForDiff(dir: string): IR {\n const compiled = compileManifest(dir);\n if (!compiled.ok || !compiled.ir) {\n const detail = compiled.failures.map((f) => `${f.file ? `${f.file}: ` : \"\"}${f.message}`).join(\"; \");\n throw new Error(`cannot compile '${dir}' for comparison — ${detail}`);\n }\n return compiled.ir;\n}\n\n// ---------------------------------------------------------------------------------------\n// The whole loop, including the probe leg (ADD-37 §6 step 6)\n// ---------------------------------------------------------------------------------------\n\nexport interface RunInitOptions extends CommitOptions {\n /** The `--probe` opt-in. Absent/false ⇒ NO request is made, under any circumstances, for\n * any capability, whatever the Decision Record says. Opt-in at the top level, then gated\n * again per capability (R-8). */\n probe?: boolean;\n /** False for CI and for a Decision Record file. Governs only the non-`GET`/`HEAD` second\n * confirmation, which is a human act. */\n interactive?: boolean;\n /** Threaded to `invokeRest` for env resolution and, in tests, a stub fetch. */\n invoke?: RecordContractOptions;\n}\n\nexport interface InitResult extends LoopResult {\n emitted: EmitResult;\n /** One entry per kept decision when probing, empty otherwise. */\n probes: ProbeReport[];\n /** What the real `runVerify` said about the contracts that were written. */\n verifications: { capabilityId: string; status: string; detail: string }[];\n}\n\n/**\n * Draft Model + Decision Record → a compiling manifest on disk, or nothing at all.\n *\n * The sequence, and why it is this shape:\n *\n * 1. emit WITHOUT contracts, materialize, compile. The probe needs a compiled `IRTool` — it\n * calls the backend the way the manifest says to, not the way the draft implies.\n * 2. probe (gated per capability), producing recordings.\n * 3. re-emit WITH the recordings, materialize again, compile again, and run the REAL\n * `runVerify` over that directory. A contract that cannot be replayed is dropped here,\n * before anything reaches the developer.\n * 4. emit a final time with only the surviving contracts, and commit.\n *\n * Three materializations rather than one, deliberately: each stage compiles the exact bytes\n * the next stage acts on, so \"a compiling manifest was written\" is never inferred from a\n * different set of bytes than the ones that landed.\n */\nexport async function runInit(draft: DraftModel, record: DecisionRecord, opts: RunInitOptions): Promise<InitResult> {\n const kept = keptDecisions(record);\n const emptyResult = (emitted: EmitResult, failures: LoopFailure[]): InitResult => ({\n ok: false,\n written: [],\n failures,\n emitted,\n probes: [],\n verifications: [],\n });\n\n const firstPass = emit(draft, record);\n if (firstPass.files.size === 0) {\n // D-7's manifest-level refusal, already decided by the emitter (an empty confirmed set, an\n // invalid company id). Nothing is written and the notes say why.\n return emptyResult(firstPass, [{ code: \"empty-file-set\", message: \"the emitter refused — see the report's notes\" }]);\n }\n\n if (opts.probe !== true) {\n const committed = commitFileSet(firstPass.files, opts);\n return { ...committed, emitted: firstPass, probes: [], verifications: [] };\n }\n\n const staging = mkdtempSync(join(opts.tmpRoot ?? tmpdir(), \"archstone-init-probe-\"));\n try {\n writeFileSet(staging, firstPass.files);\n const compiled = compileManifest(staging);\n if (!compiled.ok || !compiled.ir) return emptyResult(firstPass, compiled.failures);\n\n const probes = await runProbes(compiled.ir, kept, { ...opts.invoke, interactive: opts.interactive === true });\n\n const recorded = new Map<string, RecordedContract>();\n for (const probe of probes) if (probe.contract) recorded.set(probe.capabilityId, probe.contract);\n\n if (recorded.size === 0) {\n const committed = commitFileSet(firstPass.files, opts);\n return { ...committed, emitted: firstPass, probes, verifications: [] };\n }\n\n // Re-emit with the recordings and REPLAY them, in a second staging directory, before any\n // of it is offered to the developer (R-1).\n const replayDir = mkdtempSync(join(opts.tmpRoot ?? tmpdir(), \"archstone-init-replay-\"));\n try {\n const withContracts = emit(draft, record, recorded);\n writeFileSet(replayDir, withContracts.files);\n const recompiled = compileManifest(replayDir);\n if (!recompiled.ok || !recompiled.ir) return emptyResult(withContracts, recompiled.failures);\n\n const { green, reports } = await verifyRecorded(recompiled.ir, replayDir, opts.invoke);\n const survivors = new Map([...recorded].filter(([id]) => green.has(id)));\n\n // A contract that recorded green and then failed its own replay is dropped, not shipped.\n // The manifest still lands; only the safety net that could not be trusted is withheld.\n const finalPass = survivors.size === recorded.size ? withContracts : emit(draft, record, survivors);\n const committed = commitFileSet(finalPass.files, opts);\n return { ...committed, emitted: finalPass, probes, verifications: reports };\n } finally {\n rmSync(replayDir, { recursive: true, force: true });\n }\n } finally {\n rmSync(staging, { recursive: true, force: true });\n }\n}\n","// @archstone/init — the probe leg (ADD-37 §6 step 6, D-6, R-1, R-8).\n//\n// THE ONE FAILURE THE BUSINESS OWNER ACTUALLY FEARS is that a scaffolding tool pointed at\n// their production API writes something. So the gate below has two independent conditions and\n// both are required, and neither of them lives in this file's callee:\n//\n// 1. a CONFIRMED `effect: read` — a human said so, at a gate, per capability; and\n// 2. the METHOD rule — `GET`/`HEAD` ride on that confirmation alone, anything else needs a\n// SECOND, separate explicit confirmation, and in non-interactive mode a non-`GET`/`HEAD`\n// probe is refused outright, with no flag that enables one.\n//\n// `GET`-only would be the wrong gate and is worth saying why: `tourism.search` is a\n// `POST /v1/search` with `effect: read`, the canonical search shape. The method rule is a\n// second condition ON TOP of the confirmed read, never a substitute for it.\n//\n// This module lives in the `/loop` entry, not the root: it reaches the network (through\n// `@archstone/runtime/verify`, never through an HTTP client of its own) and the root export is\n// pure. `init` opens no socket — it asks the module that already owns record-and-replay to do\n// it, so the fixture written here is by construction the artifact `verify` will replay (R-1).\n\nimport { recordContract, runVerify, type ContractRecording, type ProbeOutcome, type RecordContractOptions } from \"@archstone/runtime/verify\";\nimport type { IR, IRTool } from \"@archstone/compiler\";\nimport type { CapabilityDecision } from \"./decisions\";\nimport type { RecordedContract } from \"./emit\";\n\n/** Why a probe did not happen. Distinct from `ProbeOutcome`, which is why one that DID happen\n * ended the way it did — conflating them would let \"we chose not to call\" and \"we called and\n * it failed\" share a word, and those are opposite facts about a backend. */\nexport type ProbeRefusal =\n /** The human did not consent. The default, and the common case. */\n | \"no-consent\"\n /** The confirmed effect is not `read`. No flag overrides this. */\n | \"effect-not-read\"\n /** A non-`GET`/`HEAD` method with no second explicit confirmation. */\n | \"method-not-confirmed\"\n /** A non-`GET`/`HEAD` method in non-interactive mode. Refused outright — there is\n * deliberately no flag, because the second confirmation is a HUMAN act and CI has no human. */\n | \"non-interactive-non-read-method\"\n /** §1.3: the fixture's `request` is capability input, and none was supplied. */\n | \"probe-input-unavailable\"\n /** The compiled manifest has no such tool, or the tool has no connector to call. */\n | \"not-invocable\";\n\nexport interface ProbeReport {\n capabilityId: string;\n /** `refused` means no request was issued. Everything else is an outcome of a real attempt —\n * except `not-attempted`, which means `invokeRest` declined to send one. */\n outcome: ProbeOutcome | \"refused\";\n refusal?: ProbeRefusal;\n detail: string;\n /** Present iff the recording survived a real `runVerify` replay. */\n contract?: RecordedContract;\n degraded?: string[];\n missing?: string[];\n}\n\nconst FREE_METHODS = new Set([\"GET\", \"HEAD\"]);\n\nexport interface GateContext {\n /** False for CI and for a Decision Record file. The distinction is not cosmetic: the\n * non-`GET` second confirmation is a human act, and there is no human here. */\n interactive: boolean;\n}\n\nexport type GateResult = { allowed: true; input: Record<string, unknown> } | { allowed: false; refusal: ProbeRefusal; detail: string };\n\n/**\n * R-8's gate, as a pure function so it can be tested exhaustively without a backend.\n *\n * Every refusal path returns BEFORE any caller could reach `recordContract`, and the tests\n * assert the strong form of that — \"no request is issued for any non-confirmed-read\n * capability, under any flag\" — by counting calls to an injected fetch, not by inspecting\n * this function's return value.\n */\nexport function probeGate(decision: Extract<CapabilityDecision, { keep: true }>, tool: IRTool | undefined, ctx: GateContext): GateResult {\n if (!tool || !tool.connector) {\n return { allowed: false, refusal: \"not-invocable\", detail: \"the compiled manifest has no invocable tool for this capability\" };\n }\n if (decision.probe !== true) {\n return { allowed: false, refusal: \"no-consent\", detail: \"no probe was requested for this capability\" };\n }\n if (decision.effect !== \"read\") {\n return { allowed: false, refusal: \"effect-not-read\", detail: `confirmed effect is '${decision.effect}' — \\`init\\` never issues a write` };\n }\n\n const method = (tool.connector.rest?.method ?? \"\").toUpperCase();\n if (!FREE_METHODS.has(method)) {\n if (!ctx.interactive) {\n return {\n allowed: false,\n refusal: \"non-interactive-non-read-method\",\n detail: `${method} needs a second, explicit human confirmation, and there is no human here`,\n };\n }\n if (decision.probeNonReadMethodConfirmed !== true) {\n return { allowed: false, refusal: \"method-not-confirmed\", detail: `${method} needs a second, separate confirmation beyond \\`effect: read\\`` };\n }\n }\n\n const input = decision.sampleInput;\n const missing = tool.input.filter((f) => f.required && (input === undefined || input[f.name] === undefined)).map((f) => f.name);\n if (missing.length > 0) {\n // §1.3, and the sharpest unglamorous constraint in the increment: the fixture's `request`\n // is CAPABILITY input, not an HTTP request, and a document usually cannot supply it. A\n // report line, never a fallback — and never the adapter's `example`, which may name a real\n // customer's record (D-13).\n return { allowed: false, refusal: \"probe-input-unavailable\", detail: `no sample value for required input(s): ${missing.join(\", \")}` };\n }\n return { allowed: true, input: input ?? {} };\n}\n\n/** A recording promoted to an emittable contract — or `undefined` when nothing may be written. */\nfunction contractOf(recording: ContractRecording): RecordedContract | undefined {\n if (recording.fingerprint === undefined || recording.fixture === undefined) return undefined;\n return {\n fingerprint: recording.fingerprint,\n ...(recording.shape ? { shape: recording.shape } : {}),\n recordedAt: recording.fixture.recordedAt ?? new Date(0).toISOString(),\n fixture: recording.fixture,\n };\n}\n\nexport interface RunProbesOptions extends RecordContractOptions {\n interactive: boolean;\n}\n\n/**\n * Probe every consented capability against the compiled manifest, once.\n *\n * Returns reports only — writing is the caller's job, and keeping it that way is what lets the\n * loop drop a contract after a failed replay without this function knowing about files.\n */\nexport async function runProbes(\n ir: IR,\n decisions: Extract<CapabilityDecision, { keep: true }>[],\n opts: RunProbesOptions,\n): Promise<ProbeReport[]> {\n const byId = new Map(ir.tools.map((t) => [t.id, t]));\n const reports: ProbeReport[] = [];\n\n // Sequential, not `Promise.all`: these are live calls to somebody's production backend, made\n // by a scaffolding tool the user is running for the first time. A burst is a worse first\n // impression than a wait, and nothing here is latency-sensitive.\n for (const decision of decisions) {\n const tool = byId.get(decision.capabilityId);\n const gate = probeGate(decision, tool, { interactive: opts.interactive });\n if (!gate.allowed) {\n reports.push({ capabilityId: decision.capabilityId, outcome: \"refused\", refusal: gate.refusal, detail: gate.detail });\n continue;\n }\n const recording = await recordContract(tool!, gate.input, ir.resources, opts);\n const contract = contractOf(recording);\n reports.push({\n capabilityId: decision.capabilityId,\n outcome: recording.outcome,\n detail: recording.detail,\n ...(contract ? { contract } : {}),\n ...(recording.degraded ? { degraded: recording.degraded } : {}),\n ...(recording.missing ? { missing: recording.missing } : {}),\n });\n }\n return reports;\n}\n\n/**\n * R-1's mitigation, made real: replay every just-written contract through the SHIPPED\n * `runVerify`, over the directory the files were written into, and report which ones survived.\n *\n * Not belt-and-braces. `recordContract` and `verifyTool` share a module and an `invokeRest`\n * call, which is what makes the artifact replayable in principle; this proves it in fact, on\n * this manifest, against this backend, before the developer's directory is touched. A fixture\n * that looks green at record time and cannot be replayed afterwards turns the safety net into\n * a liability, silently, for the manifest's lifetime.\n */\nexport async function verifyRecorded(\n ir: IR,\n dir: string,\n opts?: RecordContractOptions,\n): Promise<{ green: Set<string>; reports: { capabilityId: string; status: string; detail: string }[] }> {\n // #124 (ADD-124 D-8/D-9): `runVerify` now returns `{results, skipped}`, and it declines to\n // replay a `write`/`irreversible` contract by default. NO `--sandbox`-equivalent opt-in is\n // threaded through here, deliberately — uniform behaviour, no per-caller carve-out.\n //\n // In practice this is a no-op against `init`'s own output: `recordContract` is reachable only\n // through the probe gate, which refuses any non-`read` effect before recording (R-8), so every\n // fixture `init` can produce is for a `read` capability and `skipped` is always empty. The one\n // case it does bite — a manifest hand-edited to carry a `contract:` on a non-`read` capability\n // between `init` runs — is exactly the risk #124 exists to close. Such a contract lands outside\n // `green` and is dropped from the final emit, which is the correct, conservative outcome: `init`\n // commits a contract only when it has watched the shipped verifier replay it.\n const { results: reports } = await runVerify(ir.tools, dir, ir.resources, opts);\n const green = new Set(reports.filter((r) => r.status !== \"red\").map((r) => r.capabilityId));\n return { green, reports: reports.map((r) => ({ capabilityId: r.capabilityId, status: r.status, detail: r.detail })) };\n}\n"],"mappings":"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","names":[]}
{
"name": "@archstone/init",
"version": "0.14.0",
"version": "0.15.0",
"private": false,

@@ -46,6 +46,6 @@ "type": "module",

"yaml": "^2.6.1",
"@archstone/compiler": "0.14.0",
"@archstone/emitter-support": "0.14.0",
"@archstone/schema": "0.14.0",
"@archstone/runtime": "0.14.0"
"@archstone/compiler": "0.15.0",
"@archstone/emitter-support": "0.15.0",
"@archstone/runtime": "0.15.0",
"@archstone/schema": "0.15.0"
},

@@ -52,0 +52,0 @@ "devDependencies": {