@whittlelabs/sifter 0.25.0 → 0.27.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/bin.js +81 -2
- package/bin.js.map +2 -2
- package/package.json +1 -1
package/bin.js
CHANGED
|
@@ -15399,9 +15399,26 @@ var require_client = __commonJS({
|
|
|
15399
15399
|
async getJobPool(poolId) {
|
|
15400
15400
|
return this.request("GET", `/api/job-pools/${poolId}`);
|
|
15401
15401
|
}
|
|
15402
|
+
/**
|
|
15403
|
+
* Resolve a pool by exact name. Names are unique per OWNER, not globally
|
|
15404
|
+
* (whittlelabs#763), and this method lists without a principal filter, so
|
|
15405
|
+
* the same name can legitimately come back under several owners. That
|
|
15406
|
+
* reference is inherently ambiguous — and silently picking one (the old
|
|
15407
|
+
* behavior took the server's newest-first ordering) is exactly the
|
|
15408
|
+
* capture vector the per-owner constraint closed, re-opened cross-owner.
|
|
15409
|
+
* So it refuses instead: reference the pool by id, or list with explicit
|
|
15410
|
+
* principal filters, when more than one owner holds the name.
|
|
15411
|
+
*/
|
|
15402
15412
|
async resolveJobPoolByName(name) {
|
|
15403
15413
|
const pools = await this.listJobPools({ name });
|
|
15404
|
-
|
|
15414
|
+
const matches = pools.filter((p) => p.name === name);
|
|
15415
|
+
const owners = new Set(matches.map((p) => `${p.principalClass ?? ""}/${p.principalId ?? ""}`));
|
|
15416
|
+
if (owners.size > 1) {
|
|
15417
|
+
const error = new Error(`Job pool name "${name}" is ambiguous: ${matches.length} pools under ${owners.size} different owners hold it. Reference the pool by id, or resolve it with explicit principal filters (listJobPools).`);
|
|
15418
|
+
error.code = "JOB_POOL_NAME_AMBIGUOUS";
|
|
15419
|
+
throw error;
|
|
15420
|
+
}
|
|
15421
|
+
return matches[0];
|
|
15405
15422
|
}
|
|
15406
15423
|
/** Internal: resolve a `PoolRef` to a pool id. */
|
|
15407
15424
|
async resolvePoolRef(ref) {
|
|
@@ -19502,10 +19519,45 @@ var require_output_gates = __commonJS({
|
|
|
19502
19519
|
"../../packages/shuttle/dist/executors/output-gates.js"(exports2) {
|
|
19503
19520
|
"use strict";
|
|
19504
19521
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
19522
|
+
exports2.isSanctionedPaint = isSanctionedPaint;
|
|
19523
|
+
exports2.unsanctionedPaints = unsanctionedPaints;
|
|
19505
19524
|
exports2.resolvePath = resolvePath;
|
|
19506
19525
|
exports2.evaluateOutputGates = evaluateOutputGates;
|
|
19507
19526
|
exports2.renderRepairPrompt = renderRepairPrompt;
|
|
19508
19527
|
var INPUT_REF = "input:";
|
|
19528
|
+
var COLOR_BEARING = ["fill", "stroke", "color", "stop-color", "flood-color", "lighting-color"];
|
|
19529
|
+
var INERT = /* @__PURE__ */ new Set(["none", "inherit", "initial", "unset", "transparent", "currentcolor"]);
|
|
19530
|
+
function isSanctionedPaint(raw) {
|
|
19531
|
+
const value = raw.trim().toLowerCase();
|
|
19532
|
+
if (value === "")
|
|
19533
|
+
return true;
|
|
19534
|
+
if (INERT.has(value))
|
|
19535
|
+
return true;
|
|
19536
|
+
if (/^url\(\s*['"]?#[^)'"]+['"]?\s*\)$/.test(value))
|
|
19537
|
+
return true;
|
|
19538
|
+
const varMatch = /^var\(\s*(--[a-z0-9-]+)\s*(?:,([\s\S]*))?\)$/.exec(value);
|
|
19539
|
+
if (!varMatch)
|
|
19540
|
+
return false;
|
|
19541
|
+
const [, name, fallback] = varMatch;
|
|
19542
|
+
if (!name.startsWith("--color-"))
|
|
19543
|
+
return false;
|
|
19544
|
+
return fallback === void 0 || isSanctionedPaint(fallback);
|
|
19545
|
+
}
|
|
19546
|
+
function unsanctionedPaints(source) {
|
|
19547
|
+
const found = [];
|
|
19548
|
+
const attrs = COLOR_BEARING.join("|");
|
|
19549
|
+
const attribute = new RegExp(`\\b(?:${attrs})\\s*=\\s*(['"])([\\s\\S]*?)\\1`, "gi");
|
|
19550
|
+
const declaration = new RegExp(`\\b(?:${attrs})\\s*:\\s*([^;"'}\\n]+)`, "gi");
|
|
19551
|
+
for (const [, , value] of source.matchAll(attribute)) {
|
|
19552
|
+
if (!isSanctionedPaint(value))
|
|
19553
|
+
found.push(value.trim());
|
|
19554
|
+
}
|
|
19555
|
+
for (const [, value] of source.matchAll(declaration)) {
|
|
19556
|
+
if (!isSanctionedPaint(value))
|
|
19557
|
+
found.push(value.trim());
|
|
19558
|
+
}
|
|
19559
|
+
return found;
|
|
19560
|
+
}
|
|
19509
19561
|
function resolvePath(root, path) {
|
|
19510
19562
|
let ctx = root;
|
|
19511
19563
|
for (const seg of path.split(".")) {
|
|
@@ -19593,6 +19645,33 @@ var require_output_gates = __commonJS({
|
|
|
19593
19645
|
return [
|
|
19594
19646
|
`'${path}' must be a non-empty array${cond}; it was ${Array.isArray(value) ? "empty" : "absent"}.`
|
|
19595
19647
|
];
|
|
19648
|
+
},
|
|
19649
|
+
/**
|
|
19650
|
+
* `bounded_palette` — every colour in the sources at `path` must be named
|
|
19651
|
+
* by role rather than written as a value. Params:
|
|
19652
|
+
* `{ path: <output path>, roles?: <role names for the repair turn> }`.
|
|
19653
|
+
*
|
|
19654
|
+
* A drawing the model authors is markup the house did not write, and a
|
|
19655
|
+
* literal in it is a colour outside the consuming palette: unproved
|
|
19656
|
+
* against the colours beside it, unchecked for contrast on the ground it
|
|
19657
|
+
* lands on, and fixed to one theme. The consumer strips such a paint at
|
|
19658
|
+
* render, so an artifact that carries one silently loses it. Catching it
|
|
19659
|
+
* HERE is what makes that a repair the model can make while it still has
|
|
19660
|
+
* the drawing in hand, instead of a defect nobody sees until the picture
|
|
19661
|
+
* comes out plain.
|
|
19662
|
+
*/
|
|
19663
|
+
bounded_palette(params, output) {
|
|
19664
|
+
const path = String(params.path);
|
|
19665
|
+
const value = resolvePath(output, path);
|
|
19666
|
+
const sources = (Array.isArray(value) ? value : [value]).filter((v) => typeof v === "string" && v.length > 0);
|
|
19667
|
+
const offenders = [...new Set(sources.flatMap(unsanctionedPaints))];
|
|
19668
|
+
if (offenders.length === 0)
|
|
19669
|
+
return [];
|
|
19670
|
+
const roles = Array.isArray(params.roles) ? params.roles.map(String) : [];
|
|
19671
|
+
const vocabulary = roles.length > 0 ? ` Use one of: ${roles.join(", ")}.` : "";
|
|
19672
|
+
return [
|
|
19673
|
+
`'${path}' states ${offenders.length} colour value${offenders.length === 1 ? "" : "s"} directly (${offenders.slice(0, 8).join(", ")}${offenders.length > 8 ? ", \u2026" : ""}). Every colour must be named by role \u2014 var(--color-\u2026), currentColor, or none \u2014 never as a hex, rgb(), hsl() or colour name, because a value cannot adapt to the reader's theme and was never checked against the colours beside it.${vocabulary} Redraw with roles and return the whole output again.`
|
|
19674
|
+
];
|
|
19596
19675
|
}
|
|
19597
19676
|
};
|
|
19598
19677
|
function evaluateOutputGates(gates, output, inputs) {
|
|
@@ -22371,7 +22450,7 @@ var import_path = require("path");
|
|
|
22371
22450
|
var import_promises = require("fs/promises");
|
|
22372
22451
|
var import_yaml = __toESM(require_dist());
|
|
22373
22452
|
var import_shuttle = __toESM(require_dist5());
|
|
22374
|
-
var buildVersion = true ? "0.
|
|
22453
|
+
var buildVersion = true ? "0.27.0" : pkg.version;
|
|
22375
22454
|
var sifterBrand = {
|
|
22376
22455
|
product: {
|
|
22377
22456
|
id: "sifter",
|