@prismatic-io/lux 0.0.2-preview.16 → 0.0.2-preview.18

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.
Files changed (41) hide show
  1. package/lib/cli/doctor.d.ts +55 -0
  2. package/lib/cli/doctor.d.ts.map +1 -0
  3. package/lib/cli/doctor.js +14 -0
  4. package/lib/cli/doctor.js.map +1 -0
  5. package/lib/cli/program.d.ts +3 -1
  6. package/lib/cli/program.d.ts.map +1 -1
  7. package/lib/cli/program.js +22 -15
  8. package/lib/cli/program.js.map +1 -1
  9. package/lib/orchestrator/doctor.d.ts +1 -0
  10. package/lib/orchestrator/doctor.d.ts.map +1 -1
  11. package/lib/orchestrator/doctor.js +14 -6
  12. package/lib/orchestrator/doctor.js.map +1 -1
  13. package/lib/orchestrator/experiment-context.d.ts +4 -2
  14. package/lib/orchestrator/experiment-context.d.ts.map +1 -1
  15. package/lib/orchestrator/experiment-context.js.map +1 -1
  16. package/lib/orchestrator/experiment-corpus.d.ts +2 -1
  17. package/lib/orchestrator/experiment-corpus.d.ts.map +1 -1
  18. package/lib/orchestrator/experiment-corpus.js +9 -1
  19. package/lib/orchestrator/experiment-corpus.js.map +1 -1
  20. package/lib/orchestrator/experiment-identity.d.ts +3 -0
  21. package/lib/orchestrator/experiment-identity.d.ts.map +1 -1
  22. package/lib/orchestrator/experiment-identity.js +1 -1
  23. package/lib/orchestrator/experiment-identity.js.map +1 -1
  24. package/lib/orchestrator/experiment-preflight.d.ts +3 -0
  25. package/lib/orchestrator/experiment-preflight.d.ts.map +1 -0
  26. package/lib/orchestrator/experiment-preflight.js +21 -0
  27. package/lib/orchestrator/experiment-preflight.js.map +1 -0
  28. package/lib/orchestrator/experiment.d.ts +3 -1
  29. package/lib/orchestrator/experiment.d.ts.map +1 -1
  30. package/lib/orchestrator/experiment.js +3 -6
  31. package/lib/orchestrator/experiment.js.map +1 -1
  32. package/package.json +1 -1
  33. package/skills/lux-answerer/SKILL.md +1 -1
  34. package/src/cli/doctor.ts +17 -0
  35. package/src/cli/program.ts +25 -17
  36. package/src/orchestrator/doctor.ts +24 -5
  37. package/src/orchestrator/experiment-context.ts +3 -2
  38. package/src/orchestrator/experiment-corpus.ts +20 -2
  39. package/src/orchestrator/experiment-identity.ts +2 -2
  40. package/src/orchestrator/experiment-preflight.ts +27 -0
  41. package/src/orchestrator/experiment.ts +3 -5
@@ -62,6 +62,7 @@ export const DoctorOptionsSchema = z
62
62
  .object({
63
63
  cwd: z.string().min(1),
64
64
  campaigns: z.array(z.string()).optional(),
65
+ static: z.boolean().optional(),
65
66
  })
66
67
  .strict();
67
68
  export type DoctorOptions = z.input<typeof DoctorOptionsSchema>;
@@ -666,6 +667,7 @@ const inspectCampaign = async (
666
667
  config: ResolvedLuxConfig,
667
668
  registry: Registry,
668
669
  recorder: DoctorRecorder,
670
+ staticChecks: boolean,
669
671
  ): Promise<void> => {
670
672
  try {
671
673
  const loaded = await loadExperimentCampaign(path);
@@ -679,7 +681,9 @@ const inspectCampaign = async (
679
681
  placeholders.join(", "),
680
682
  );
681
683
  }
682
- const plan = await planExperimentCampaign({ config, registry, loaded }, mode);
684
+ const plan = await planExperimentCampaign({ config, registry, loaded }, mode, {
685
+ static: staticChecks,
686
+ });
683
687
  recorder.campaigns.push({ path, campaignId: loaded.campaign.id, mode, plan });
684
688
  recorder.add(
685
689
  `campaign:${loaded.campaign.id}`,
@@ -711,6 +715,7 @@ const inspectCampaigns = async (
711
715
  config: ResolvedLuxConfig,
712
716
  registry: Registry,
713
717
  recorder: DoctorRecorder,
718
+ staticChecks: boolean,
714
719
  ): Promise<void> => {
715
720
  let paths: string[];
716
721
  try {
@@ -733,7 +738,7 @@ const inspectCampaigns = async (
733
738
  );
734
739
  }
735
740
  for (const path of paths) {
736
- await inspectCampaign(path, config, registry, recorder);
741
+ await inspectCampaign(path, config, registry, recorder, staticChecks);
737
742
  }
738
743
  };
739
744
 
@@ -749,12 +754,26 @@ export const doctorProject = async (options: DoctorOptions): Promise<DoctorRepor
749
754
  validateConfiguredDrivers(config, registry, recorder);
750
755
  validateConfiguredAnswerers(config, registry, recorder);
751
756
  const caseCliTargets = await inspectCases(config, registry, recorder);
752
- await inspectCliTargets(
753
- [...configuredCliTargets(config, registry), ...caseCliTargets],
757
+ if (parsedOptions.static) {
758
+ recorder.add(
759
+ "static-checks",
760
+ "warn",
761
+ "static checks only; installed executables and campaign execution identity were not checked",
762
+ );
763
+ } else {
764
+ await inspectCliTargets(
765
+ [...configuredCliTargets(config, registry), ...caseCliTargets],
766
+ config,
767
+ recorder,
768
+ );
769
+ }
770
+ await inspectCampaigns(
771
+ parsedOptions.campaigns ?? [],
754
772
  config,
773
+ registry,
755
774
  recorder,
775
+ parsedOptions.static ?? false,
756
776
  );
757
- await inspectCampaigns(parsedOptions.campaigns ?? [], config, registry, recorder);
758
777
  return recorder.finish(config.rootDir);
759
778
  };
760
779
 
@@ -3,17 +3,18 @@ import type { ResolvedLuxConfig } from "./config.js";
3
3
  import type { discoverCases } from "./discover.js";
4
4
  import type { LoadedExperimentCampaign } from "./experiment-loader.js";
5
5
 
6
- export type EvaluationCorpus =
6
+ export type CorpusSelection =
7
7
  | {
8
8
  kind: "agent";
9
9
  cases: Awaited<ReturnType<typeof discoverCases>>["cases"];
10
- hash: string;
11
10
  }
12
11
  | {
13
12
  kind: "grader";
14
13
  hash: string;
15
14
  };
16
15
 
16
+ export type EvaluationCorpus = CorpusSelection & { hash: string };
17
+
17
18
  export type CampaignExecutionOptions = {
18
19
  config: ResolvedLuxConfig;
19
20
  registry: Registry;
@@ -13,7 +13,11 @@ import {
13
13
  import { assertDisjointAnnotationSplits, selectGraderAnnotations } from "./annotation-loader.js";
14
14
  import { discoverCases, selectCases } from "./discover.js";
15
15
  import { experimentDriverIdentity } from "./driver-identity.js";
16
- import type { CampaignExecutionOptions, EvaluationCorpus } from "./experiment-context.js";
16
+ import type {
17
+ CampaignExecutionOptions,
18
+ CorpusSelection,
19
+ EvaluationCorpus,
20
+ } from "./experiment-context.js";
17
21
  import { profileOrThrow } from "./experiment-context.js";
18
22
  import { cliIdentity, referencedAnswererCli } from "./experiment-runtime-identity.js";
19
23
  import { fixtureIdentity } from "./fixture-identity.js";
@@ -252,6 +256,21 @@ export const graderCorpusHash = async (
252
256
  export const prepareCorpus = async (
253
257
  execution: CampaignExecutionOptions,
254
258
  ): Promise<EvaluationCorpus> => {
259
+ const corpus = await inspectCorpus(execution);
260
+ if (corpus.kind === "grader") return corpus;
261
+ return {
262
+ ...corpus,
263
+ hash: await agentCorpusHash(
264
+ execution,
265
+ corpus.cases,
266
+ selectorsBySplit(execution.loaded.campaign),
267
+ ),
268
+ };
269
+ };
270
+
271
+ export const inspectCorpus = async (
272
+ execution: CampaignExecutionOptions,
273
+ ): Promise<CorpusSelection> => {
255
274
  const campaign = execution.loaded.campaign;
256
275
  const splits = selectorsBySplit(campaign);
257
276
  if (campaign.evaluation.kind === "grader") {
@@ -344,7 +363,6 @@ export const prepareCorpus = async (
344
363
  return {
345
364
  kind: "agent",
346
365
  cases: discovery.cases,
347
- hash: await agentCorpusHash(execution, discovery.cases, splits),
348
366
  };
349
367
  };
350
368
 
@@ -253,9 +253,9 @@ const authoredConfigDependencyHash = async (
253
253
  }
254
254
  return authoredDependencyGraphHash(configRoot, [...entrypoints]);
255
255
  };
256
- const validateAgentCaseProfileDrivers = async (
256
+ export const validateAgentCaseProfileDrivers = async (
257
257
  execution: CampaignExecutionOptions,
258
- corpus: Extract<EvaluationCorpus, { kind: "agent" }>,
258
+ corpus: Pick<Extract<EvaluationCorpus, { kind: "agent" }>, "cases">,
259
259
  ): Promise<void> => {
260
260
  const selected = [
261
261
  ...new Map(
@@ -0,0 +1,27 @@
1
+ import { assertValidationArgumentsBound } from "./candidates.js";
2
+ import {
3
+ type CampaignExecutionOptions,
4
+ type CorpusSelection,
5
+ profileOrThrow,
6
+ } from "./experiment-context.js";
7
+ import { inspectCorpus, prepareCorpus } from "./experiment-corpus.js";
8
+ import { evaluationIdentity, validateAgentCaseProfileDrivers } from "./experiment-identity.js";
9
+
10
+ export const preparePlanningCorpus = async (
11
+ execution: CampaignExecutionOptions,
12
+ mode: "experiment" | "optimize",
13
+ staticChecks: boolean,
14
+ ): Promise<CorpusSelection> => {
15
+ if (!staticChecks) {
16
+ const corpus = await prepareCorpus(execution);
17
+ await evaluationIdentity(execution, corpus, mode);
18
+ return corpus;
19
+ }
20
+ const corpus = await inspectCorpus(execution);
21
+ const campaign = execution.loaded.campaign;
22
+ for (const profileId of campaign.profiles) profileOrThrow(execution.config, profileId);
23
+ if (corpus.kind === "agent") await validateAgentCaseProfileDrivers(execution, corpus);
24
+ for (const validation of campaign.subject.validate)
25
+ assertValidationArgumentsBound(execution.loaded.subjectRoot, validation.args);
26
+ return corpus;
27
+ };
@@ -48,6 +48,7 @@ import {
48
48
  resolvedProfileSnapshot,
49
49
  runtimeCliReferences,
50
50
  } from "./experiment-identity.js";
51
+ import { preparePlanningCorpus } from "./experiment-preflight.js";
51
52
  import {
52
53
  type ExperimentEvaluation,
53
54
  loadExperimentCandidates,
@@ -182,6 +183,7 @@ const evaluateAcross = async (options: {
182
183
  export const planExperimentCampaign = async (
183
184
  execution: CampaignExecutionOptions,
184
185
  mode: "experiment" | "optimize",
186
+ options: { static?: boolean } = {},
185
187
  ): Promise<ExperimentCampaignPlan> => {
186
188
  const campaign = execution.loaded.campaign;
187
189
  if (mode === "optimize") {
@@ -192,11 +194,7 @@ export const planExperimentCampaign = async (
192
194
  }
193
195
  const baseline = await captureSeedCandidate(execution.loaded.subjectRoot, campaign.subject);
194
196
  await assertGraderSubject(execution, baseline);
195
- const corpus = await prepareCorpus(execution);
196
- // Plan is the deterministic preflight for execution. Build the exact same
197
- // identity now so profile, behavior-tree, and custom CLI failures happen
198
- // before a user approves any model spend.
199
- await evaluationIdentity(execution, corpus, mode);
197
+ const corpus = await preparePlanningCorpus(execution, mode, options.static ?? false);
200
198
  const splitSelectors = selectorsBySplit(campaign);
201
199
  const graderAnnotations = execution.loaded.graderAnnotations?.annotations ?? [];
202
200
  const splits = splitSelectors.map(({ name, selector }) => ({