@sanity/ailf 4.0.4 → 4.0.6
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/dist/_vendor/ailf-core/constants.d.ts +22 -0
- package/dist/_vendor/ailf-core/constants.js +22 -0
- package/dist/_vendor/ailf-core/index.d.ts +1 -0
- package/dist/_vendor/ailf-core/index.js +1 -0
- package/dist/adapters/api-client/build-request.js +7 -2
- package/dist/adapters/task-sources/repo-schemas.js +6 -2
- package/dist/commands/pipeline-action.js +16 -0
- package/dist/orchestration/steps/fetch-docs-step.js +9 -4
- package/dist/orchestration/steps/generate-configs-step.d.ts +6 -5
- package/dist/orchestration/steps/generate-configs-step.js +18 -11
- package/dist/pipeline/run-context.d.ts +6 -1
- package/dist/pipeline/run-context.js +17 -2
- package/package.json +1 -1
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @sanity/ailf-core — Cross-package sentinel constants.
|
|
3
|
+
*
|
|
4
|
+
* Sentinel strings shared between the init template (which writes them
|
|
5
|
+
* into `.github/workflows/ailf-eval.yml`) and the consumers that must
|
|
6
|
+
* recognize them (run-context builder, caller envelope assembly, CLI
|
|
7
|
+
* pre-flight checks). Centralizing here keeps the placeholder definition
|
|
8
|
+
* in exactly one place — duplicating the literal across producers and
|
|
9
|
+
* consumers historically caused the literal to leak into Sanity reports
|
|
10
|
+
* (W0143).
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* The literal string `ailf init` writes into the scaffolded GitHub Actions
|
|
14
|
+
* workflow as the value of `AILF_OWNER_TEAM`. Consumers treat this string
|
|
15
|
+
* as semantically unset — it must never end up persisted as a real team
|
|
16
|
+
* slug on a run report.
|
|
17
|
+
*
|
|
18
|
+
* @see packages/core/examples/ailf-eval-workflow.yml — the canonical source
|
|
19
|
+
* @see packages/eval/src/pipeline/run-context.ts — sanitizes on read
|
|
20
|
+
* @see packages/eval/src/adapters/api-client/build-request.ts — drops on the wire
|
|
21
|
+
*/
|
|
22
|
+
export declare const PLACEHOLDER_OWNER_TEAM = "<REPLACE-WITH-YOUR-TEAM-SLUG>";
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @sanity/ailf-core — Cross-package sentinel constants.
|
|
3
|
+
*
|
|
4
|
+
* Sentinel strings shared between the init template (which writes them
|
|
5
|
+
* into `.github/workflows/ailf-eval.yml`) and the consumers that must
|
|
6
|
+
* recognize them (run-context builder, caller envelope assembly, CLI
|
|
7
|
+
* pre-flight checks). Centralizing here keeps the placeholder definition
|
|
8
|
+
* in exactly one place — duplicating the literal across producers and
|
|
9
|
+
* consumers historically caused the literal to leak into Sanity reports
|
|
10
|
+
* (W0143).
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* The literal string `ailf init` writes into the scaffolded GitHub Actions
|
|
14
|
+
* workflow as the value of `AILF_OWNER_TEAM`. Consumers treat this string
|
|
15
|
+
* as semantically unset — it must never end up persisted as a real team
|
|
16
|
+
* slug on a run report.
|
|
17
|
+
*
|
|
18
|
+
* @see packages/core/examples/ailf-eval-workflow.yml — the canonical source
|
|
19
|
+
* @see packages/eval/src/pipeline/run-context.ts — sanitizes on read
|
|
20
|
+
* @see packages/eval/src/adapters/api-client/build-request.ts — drops on the wire
|
|
21
|
+
*/
|
|
22
|
+
export const PLACEHOLDER_OWNER_TEAM = "<REPLACE-WITH-YOUR-TEAM-SLUG>";
|
|
@@ -17,6 +17,7 @@ export * from "./services/index.js";
|
|
|
17
17
|
export * from "./examples/index.js";
|
|
18
18
|
export * from "./artifact-registry.js";
|
|
19
19
|
export * from "./batch-signing.js";
|
|
20
|
+
export * from "./constants.js";
|
|
20
21
|
export { defineCanaryTasks, defineConfig, defineFeatures, defineModeBase, defineModels, definePricingTable, definePreset, definePrompts, defineRubrics, defineSchedules, defineSinks, defineSources, defineTask, defineTestBudgets, defineThresholds, } from "./config-helpers.js";
|
|
21
22
|
export type { PricingEntry, PromptEntry, SourceEntry, } from "./config-helpers.js";
|
|
22
23
|
export { env } from "./env-helper.js";
|
|
@@ -17,6 +17,7 @@ export * from "./services/index.js";
|
|
|
17
17
|
export * from "./examples/index.js";
|
|
18
18
|
export * from "./artifact-registry.js";
|
|
19
19
|
export * from "./batch-signing.js";
|
|
20
|
+
export * from "./constants.js";
|
|
20
21
|
// ---------------------------------------------------------------------------
|
|
21
22
|
// Architecture overhaul — Phase 0 helpers
|
|
22
23
|
// ---------------------------------------------------------------------------
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
*/
|
|
15
15
|
import { existsSync } from "fs";
|
|
16
16
|
import { resolve } from "path";
|
|
17
|
-
import { PipelineRequestSchema, } from "../../_vendor/ailf-core/index.js";
|
|
17
|
+
import { PLACEHOLDER_OWNER_TEAM, PipelineRequestSchema, } from "../../_vendor/ailf-core/index.js";
|
|
18
18
|
import { LEGACY_EVAL_MODE_ALIASES, isRunClassification, } from "../../_vendor/ailf-shared/index.js";
|
|
19
19
|
import { RepoTaskSource } from "../task-sources/repo-task-source.js";
|
|
20
20
|
const LEGACY_LITERACY_VARIANT_SET = new Set(LEGACY_EVAL_MODE_ALIASES);
|
|
@@ -316,7 +316,12 @@ export function buildCallerEnvelope(config) {
|
|
|
316
316
|
}
|
|
317
317
|
}
|
|
318
318
|
// Owner: flag > env. Team required, individual optional.
|
|
319
|
-
|
|
319
|
+
// W0143: drop the init-template placeholder — when a consumer hasn't
|
|
320
|
+
// filled in their team slug yet we treat it as unset rather than
|
|
321
|
+
// shipping the literal `<REPLACE-WITH-YOUR-TEAM-SLUG>` across the wire
|
|
322
|
+
// and into the report's Provenance card.
|
|
323
|
+
const rawTeam = config.ownerTeamOption ?? process.env.AILF_OWNER_TEAM?.trim() ?? undefined;
|
|
324
|
+
const team = rawTeam === PLACEHOLDER_OWNER_TEAM ? undefined : rawTeam;
|
|
320
325
|
const individual = config.ownerIndividualOption ??
|
|
321
326
|
process.env.AILF_OWNER_INDIVIDUAL?.trim() ??
|
|
322
327
|
process.env.GITHUB_ACTOR?.trim() ??
|
|
@@ -376,12 +376,16 @@ export function parseCanonicalTaskFile(raw, filename) {
|
|
|
376
376
|
// (featureArea, canonicalDocs, assert, vars), surface a helpful error
|
|
377
377
|
// message telling them what the canonical names are.
|
|
378
378
|
// ---------------------------------------------------------------------------
|
|
379
|
+
// Phrasing avoids literal `{` and `}` characters on purpose. GitHub Actions
|
|
380
|
+
// registers each line of a multi-line secret as a mask, so a pretty-printed
|
|
381
|
+
// JSON secret introduces standalone `{` / `}` masks that then redact every
|
|
382
|
+
// `{` / `}` in subsequent log output. See W0144.
|
|
379
383
|
/** Old field names from @sanity/ailf-tasks → canonical equivalents */
|
|
380
384
|
const LEGACY_FIELD_MAP = {
|
|
381
385
|
featureArea: "area",
|
|
382
|
-
canonicalDocs: "context.docs (
|
|
386
|
+
canonicalDocs: "context.docs (move the docs array under a context parent)",
|
|
383
387
|
assert: "assertions",
|
|
384
|
-
vars: "prompt (
|
|
388
|
+
vars: "prompt (move the text string under a prompt parent)",
|
|
385
389
|
};
|
|
386
390
|
/**
|
|
387
391
|
* Detect legacy field names in raw task data and return helpful messages.
|
|
@@ -20,6 +20,7 @@ import { buildAppContext, parseArtifactUploadEnv, } from "../orchestration/build
|
|
|
20
20
|
import { buildStepSequence } from "../orchestration/build-step-sequence.js";
|
|
21
21
|
import { orchestratePipeline } from "../orchestration/pipeline-orchestrator.js";
|
|
22
22
|
import { load } from "js-yaml";
|
|
23
|
+
import { PLACEHOLDER_OWNER_TEAM } from "../_vendor/ailf-core/index.js";
|
|
23
24
|
import { parseRepoConfig, } from "../adapters/task-sources/repo-schemas.js";
|
|
24
25
|
import { getCallerCwd, resolveOutputDir } from "./shared/resolve-output-dir.js";
|
|
25
26
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
@@ -406,6 +407,7 @@ function resolveRepoTasksPath(callerCwd, explicitPath, taskSourceType) {
|
|
|
406
407
|
* 4. Delegate to the PipelineOrchestrator
|
|
407
408
|
*/
|
|
408
409
|
export async function executePipeline(cliOpts) {
|
|
410
|
+
warnIfPlaceholderOwnerTeam();
|
|
409
411
|
// When --config is provided, resolve config from file instead of CLI flags
|
|
410
412
|
if (cliOpts.config) {
|
|
411
413
|
const { existsSync } = await import("fs");
|
|
@@ -493,6 +495,20 @@ export async function executePipeline(cliOpts) {
|
|
|
493
495
|
// ---------------------------------------------------------------------------
|
|
494
496
|
// Internal helpers
|
|
495
497
|
// ---------------------------------------------------------------------------
|
|
498
|
+
/**
|
|
499
|
+
* W0143: warn once on stderr when the consumer is still running with the
|
|
500
|
+
* unedited init-template placeholder for AILF_OWNER_TEAM. The run
|
|
501
|
+
* continues — provenance just gets attributed as unset rather than the
|
|
502
|
+
* literal placeholder.
|
|
503
|
+
*/
|
|
504
|
+
function warnIfPlaceholderOwnerTeam() {
|
|
505
|
+
if (process.env.AILF_OWNER_TEAM?.trim() !== PLACEHOLDER_OWNER_TEAM)
|
|
506
|
+
return;
|
|
507
|
+
console.warn(` ⚠️ AILF_OWNER_TEAM is still set to the init-template placeholder ` +
|
|
508
|
+
`"${PLACEHOLDER_OWNER_TEAM}". Provenance will be logged as unset. ` +
|
|
509
|
+
`Set a real team slug in .github/workflows/ailf-eval.yml (or unset ` +
|
|
510
|
+
`AILF_OWNER_TEAM) to attribute this run.`);
|
|
511
|
+
}
|
|
496
512
|
/**
|
|
497
513
|
* Resolve CLI options into typed ResolvedOptions.
|
|
498
514
|
*/
|
|
@@ -34,11 +34,16 @@ export class FetchDocsStep {
|
|
|
34
34
|
// a mismatch where configs reference context files that were never
|
|
35
35
|
// fetched.
|
|
36
36
|
//
|
|
37
|
-
//
|
|
38
|
-
//
|
|
39
|
-
//
|
|
37
|
+
// Adapter path: ctx.taskSource handles both content-lake and repo modes.
|
|
38
|
+
// The composition root wires the right adapter (ContentLakeTaskSource
|
|
39
|
+
// or RepoTaskSource) per taskSourceType. RepoTaskSource loads BOTH
|
|
40
|
+
// .yaml and .task.ts files — necessary for external-consumer evals
|
|
41
|
+
// that materialize inline tasks as YAML (W0148).
|
|
42
|
+
// Filesystem path: load from .task.ts files (legacy unset path —
|
|
43
|
+
// AILF defaults from tasks/${mode}/ + optional repoTasksPath augment).
|
|
40
44
|
let allTasks;
|
|
41
|
-
if (ctx.config.taskSourceType === "content-lake"
|
|
45
|
+
if (ctx.config.taskSourceType === "content-lake" ||
|
|
46
|
+
ctx.config.taskSourceType === "repo") {
|
|
42
47
|
const filter = {
|
|
43
48
|
...(ctx.config.areas?.length ? { areas: ctx.config.areas } : {}),
|
|
44
49
|
...(ctx.config.tasks?.length ? { taskIds: ctx.config.tasks } : {}),
|
|
@@ -19,13 +19,14 @@ export declare class GenerateConfigsStep implements PipelineStep {
|
|
|
19
19
|
private compileSingleMode;
|
|
20
20
|
private loadTasks;
|
|
21
21
|
/**
|
|
22
|
-
* Load tasks
|
|
22
|
+
* Load tasks via ctx.taskSource (the composition-root-wired adapter).
|
|
23
23
|
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
24
|
+
* Used for both `taskSourceType === "content-lake"` (ContentLakeTaskSource)
|
|
25
|
+
* and `taskSourceType === "repo"` (RepoTaskSource). Filtering by
|
|
26
|
+
* area/task/tag is delegated to the adapter — ContentLakeTaskSource
|
|
27
|
+
* pushes it into the GROQ query, RepoTaskSource applies it in-memory.
|
|
27
28
|
*/
|
|
28
|
-
private
|
|
29
|
+
private loadTasksFromAdapter;
|
|
29
30
|
/**
|
|
30
31
|
* Load tasks from filesystem .task.ts files.
|
|
31
32
|
*
|
|
@@ -209,23 +209,30 @@ export class GenerateConfigsStep {
|
|
|
209
209
|
// Task loading — unified for all modes
|
|
210
210
|
// ---------------------------------------------------------------------------
|
|
211
211
|
async loadTasks(ctx, mode, state) {
|
|
212
|
-
//
|
|
213
|
-
//
|
|
214
|
-
// Studio-owned
|
|
215
|
-
|
|
216
|
-
|
|
212
|
+
// Adapter path — use ctx.taskSource. The composition root wires the
|
|
213
|
+
// right adapter for each taskSourceType:
|
|
214
|
+
// - "content-lake" → ContentLakeTaskSource (Studio-owned ailf.task docs)
|
|
215
|
+
// - "repo" → RepoTaskSource (loads .yaml AND .task.ts from repoTasksPath)
|
|
216
|
+
// Routing both through ctx.taskSource keeps the orchestration step
|
|
217
|
+
// file-format-agnostic (W0148: external-consumer evals materialize
|
|
218
|
+
// inline tasks as .yaml, which loadPipelineTasks can't read).
|
|
219
|
+
if (ctx.config.taskSourceType === "content-lake" ||
|
|
220
|
+
ctx.config.taskSourceType === "repo") {
|
|
221
|
+
return this.loadTasksFromAdapter(ctx, state);
|
|
217
222
|
}
|
|
218
|
-
// Filesystem path — load from .task.ts files (
|
|
223
|
+
// Filesystem path — load from .task.ts files (legacy unset path:
|
|
224
|
+
// AILF defaults from tasks/${mode}/ + optional repoTasksPath augment).
|
|
219
225
|
return this.loadTasksFromFilesystem(ctx, mode, state);
|
|
220
226
|
}
|
|
221
227
|
/**
|
|
222
|
-
* Load tasks
|
|
228
|
+
* Load tasks via ctx.taskSource (the composition-root-wired adapter).
|
|
223
229
|
*
|
|
224
|
-
*
|
|
225
|
-
*
|
|
226
|
-
*
|
|
230
|
+
* Used for both `taskSourceType === "content-lake"` (ContentLakeTaskSource)
|
|
231
|
+
* and `taskSourceType === "repo"` (RepoTaskSource). Filtering by
|
|
232
|
+
* area/task/tag is delegated to the adapter — ContentLakeTaskSource
|
|
233
|
+
* pushes it into the GROQ query, RepoTaskSource applies it in-memory.
|
|
227
234
|
*/
|
|
228
|
-
async
|
|
235
|
+
async loadTasksFromAdapter(ctx, state) {
|
|
229
236
|
const filter = {
|
|
230
237
|
...(ctx.config.areas?.length ? { areas: ctx.config.areas } : {}),
|
|
231
238
|
...(ctx.config.tasks?.length ? { taskIds: ctx.config.tasks } : {}),
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
*
|
|
13
13
|
* @see docs/decisions/D0032-run-anchored-artifact-store.md (§ Move 5 — Drift Prevention)
|
|
14
14
|
*/
|
|
15
|
-
import type
|
|
15
|
+
import { type Logger, type RunContext } from "../_vendor/ailf-core/index.d.ts";
|
|
16
16
|
import { type RunClassification, type RunExecutor, type RunExecutorSurface, type RunHost, type RunLineage, type RunOwner, type RunTool } from "../_vendor/ailf-shared/index.d.ts";
|
|
17
17
|
import type { ResolvedSourceConfig } from "../sources.js";
|
|
18
18
|
import type { EvalMode } from "./types.js";
|
|
@@ -92,6 +92,11 @@ export declare function detectClassification(log: Logger): RunClassification;
|
|
|
92
92
|
/**
|
|
93
93
|
* Resolve `owner` from `AILF_OWNER_TEAM` (+ optional
|
|
94
94
|
* `AILF_OWNER_INDIVIDUAL`). `team` is free-form; default is `"unknown"`.
|
|
95
|
+
*
|
|
96
|
+
* The init-template placeholder (`PLACEHOLDER_OWNER_TEAM`) is treated as
|
|
97
|
+
* if the env var were unset — consumers that haven't filled it in yet
|
|
98
|
+
* end up with `team: "unknown"` instead of the literal placeholder being
|
|
99
|
+
* persisted onto the report (W0143).
|
|
95
100
|
*/
|
|
96
101
|
export declare function detectOwner(): RunOwner;
|
|
97
102
|
/**
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
import { execSync } from "node:child_process";
|
|
16
16
|
import { createRequire } from "node:module";
|
|
17
17
|
import * as os from "node:os";
|
|
18
|
+
import { PLACEHOLDER_OWNER_TEAM, } from "../_vendor/ailf-core/index.js";
|
|
18
19
|
import { isRunClassification, } from "../_vendor/ailf-shared/index.js";
|
|
19
20
|
import { ConsoleLogger } from "../adapters/loggers/index.js";
|
|
20
21
|
import { tryLoadConfigFile } from "./compiler/config-loader.js";
|
|
@@ -45,7 +46,15 @@ export function buildRunContext(input) {
|
|
|
45
46
|
// preservation across the --remote boundary.
|
|
46
47
|
const envelope = input.callerEnvelope;
|
|
47
48
|
const classification = envelope?.classification ?? detectClassification(log);
|
|
48
|
-
|
|
49
|
+
// W0143: a caller-supplied owner whose team is the init-template
|
|
50
|
+
// placeholder is treated as "user hasn't filled this in yet" — drop the
|
|
51
|
+
// envelope owner and fall through to env detection (which performs the
|
|
52
|
+
// same sanitization on AILF_OWNER_TEAM). Avoids persisting the literal
|
|
53
|
+
// placeholder verbatim on the report.
|
|
54
|
+
const sanitizedEnvelopeOwner = envelope?.owner && envelope.owner.team !== PLACEHOLDER_OWNER_TEAM
|
|
55
|
+
? envelope.owner
|
|
56
|
+
: undefined;
|
|
57
|
+
const owner = sanitizedEnvelopeOwner ?? detectOwner();
|
|
49
58
|
const executor = envelope?.executor ?? detectExecutor();
|
|
50
59
|
// `tool` and `host` are server-environment facts — they always reflect
|
|
51
60
|
// where this pipeline is actually running, never what a caller claimed.
|
|
@@ -184,9 +193,15 @@ export function detectClassification(log) {
|
|
|
184
193
|
/**
|
|
185
194
|
* Resolve `owner` from `AILF_OWNER_TEAM` (+ optional
|
|
186
195
|
* `AILF_OWNER_INDIVIDUAL`). `team` is free-form; default is `"unknown"`.
|
|
196
|
+
*
|
|
197
|
+
* The init-template placeholder (`PLACEHOLDER_OWNER_TEAM`) is treated as
|
|
198
|
+
* if the env var were unset — consumers that haven't filled it in yet
|
|
199
|
+
* end up with `team: "unknown"` instead of the literal placeholder being
|
|
200
|
+
* persisted onto the report (W0143).
|
|
187
201
|
*/
|
|
188
202
|
export function detectOwner() {
|
|
189
|
-
const
|
|
203
|
+
const rawTeam = process.env.AILF_OWNER_TEAM?.trim();
|
|
204
|
+
const team = rawTeam && rawTeam !== PLACEHOLDER_OWNER_TEAM ? rawTeam : "unknown";
|
|
190
205
|
const individual = process.env.AILF_OWNER_INDIVIDUAL?.trim() || undefined;
|
|
191
206
|
return individual ? { individual, team } : { team };
|
|
192
207
|
}
|