FretGuard pack lifecycle
Continue from the registered source, specRevision, and dataira client in
the FretGuard OpenAPI pilot.
const packs = dataira.analyticalPacks({ projectId: process.env.DATAIRA_PROJECT_ID!, environmentId: process.env.DATAIRA_ENVIRONMENT_ID! });
const preset = (await packs.listPresets()).find(p => p.id === "transport-control-tower" && p.version === "1.0.0");
if (!preset) throw new Error("Pinned preset unavailable");
let draft = await packs.createDraft({ name: "FretGuard", idempotencyKey: crypto.randomUUID() });
let imported = await packs.import({ packId: draft.packId, expectedRevision: draft.revision,
idempotencyKey: crypto.randomUUID(), import: { kind: "preset", producer: "dataira",
presetId: preset.id, presetVersion: preset.version, presetDigest: preset.digest } });
imported = await packs.analyzeOpenApi({ packId: draft.packId, expectedRevision: imported.revision.revision,
idempotencyKey: crypto.randomUUID(), datasourceId: source.id, generation: source.generation,
specRevision, reviewedSelections: { operationIds: ["listCostVariance", "simulateCostScenario"] } });
const markdown = `---\nmanifest: {"apiVersion":"dataira.io/proposal/v1"}\nknowledgeId: fretguard-guide\ntitle: FretGuard guide\n---\nPartner-reviewed domain notes.`;
imported = await packs.import({ packId: draft.packId, expectedRevision: imported.revision.revision,
idempotencyKey: crypto.randomUUID(), import: { kind: "markdown", producer: "fretguard-owner", content: markdown } });
imported = await packs.import({ packId: draft.packId, expectedRevision: imported.revision.revision,
idempotencyKey: crypto.randomUUID(), import: { kind: "agent_proposal", producer: "partner-code-scanner",
content: JSON.stringify({ apiVersion: "dataira.io/proposal/v1" }),
repository: "https://git.example/fretguard.git", commit: "abc1234", files: ["src/costs.ts"] } });
const changes = await packs.diff({ packId: draft.packId, fromRevision: draft.revision,
toRevision: imported.revision.revision });
const valid = await packs.validate({ packId: draft.packId, revision: imported.revision.revision,
expectedRevision: imported.revision.revision, idempotencyKey: crypto.randomUUID() });
if (!valid.valid) throw new Error(JSON.stringify(valid.diagnostics));
const reviewed = await packs.submitReview({ packId: draft.packId, revision: imported.revision.revision,
expectedRevision: imported.revision.revision, idempotencyKey: crypto.randomUUID() });
const published = await packs.publish({ packId: draft.packId, revision: reviewed.revision,
expectedRevision: reviewed.revision, expectedActiveGeneration:
(await packs.getActive())?.generation ?? 0, idempotencyKey: crypto.randomUUID() });
const exported = await packs.export(draft.packId, published.revision);
Canonical JSON or YAML is an alternative import, never another context. Review
changes, resolve every conflict explicitly, and retain exported.manifestHash.
After publishing a later revision, restore this one with exact concurrency state:
const latest = await packs.get(draft.packId);
const active = await packs.getActive();
if (!active) throw new Error("No active context");
await packs.rollback({ packId: draft.packId, revision: published.revision,
expectedRevision: latest.revision, expectedActiveGeneration: active.generation,
idempotencyKey: crypto.randomUUID() });