@interf/compiler 0.18.0 → 0.21.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/README.md +87 -73
- package/dist/cli/commands/mcp.d.ts +0 -34
- package/dist/cli/commands/mcp.js +246 -45
- package/dist/cli/commands/method.js +261 -15
- package/dist/cli/commands/prep.js +61 -16
- package/dist/cli/commands/runs.js +103 -9
- package/dist/cli/commands/status.js +4 -2
- package/dist/cli/commands/test.d.ts +10 -0
- package/dist/cli/commands/{verify.js → test.js} +16 -18
- package/dist/cli/commands/web.js +82 -8
- package/dist/cli/commands/wizard.js +36 -37
- package/dist/cli/index.d.ts +2 -2
- package/dist/cli/index.js +3 -3
- package/dist/compiler-ui/404.html +1 -1
- package/dist/compiler-ui/__next.__PAGE__.txt +5 -5
- package/dist/compiler-ui/__next._full.txt +13 -12
- package/dist/compiler-ui/__next._head.txt +3 -3
- package/dist/compiler-ui/__next._index.txt +5 -4
- package/dist/compiler-ui/__next._tree.txt +4 -3
- package/dist/compiler-ui/_next/static/chunks/01646j7yi.w5a.css +1 -0
- package/dist/compiler-ui/_next/static/chunks/{0n51hrfoufc7g.js → 02f_.8.ebn556.js} +1 -1
- package/dist/compiler-ui/_next/static/chunks/02r7siaw-_p5w.js +1 -0
- package/dist/compiler-ui/_next/static/chunks/{08m7vf5asqlsm.js → 04d0ly-7xb~-j.js} +10 -10
- package/dist/compiler-ui/_next/static/chunks/0fhs9psnxqd8s.js +1 -0
- package/dist/compiler-ui/_next/static/chunks/0mssmhpbifj15.css +2 -0
- package/dist/compiler-ui/_next/static/chunks/0nypu~ddwxari.js +116 -0
- package/dist/compiler-ui/_next/static/chunks/0p3s8iyhgcww2.js +31 -0
- package/dist/compiler-ui/_next/static/chunks/0tjf-vu_rz8s0.css +1 -0
- package/dist/compiler-ui/_next/static/chunks/0u6p3fpbbfgtl.js +1 -0
- package/dist/compiler-ui/_next/static/chunks/0wpx5..8dnh0w.js +1 -0
- package/dist/compiler-ui/_next/static/chunks/0y0uj160p0ts~.js +1 -0
- package/dist/compiler-ui/_next/static/chunks/10t8l~_oenf.c.js +1 -0
- package/dist/compiler-ui/_next/static/chunks/13gz9e7z~imx1.js +5 -0
- package/dist/compiler-ui/_next/static/chunks/156xed-b6czaw.js +1 -0
- package/dist/compiler-ui/_next/static/chunks/{turbopack-0.uq1k8c0j4s..js → turbopack-02-3e_c-yz~5g.js} +1 -1
- package/dist/compiler-ui/_next/static/chunks/{turbopack-10e~t1yzi4svj.js → turbopack-0apv8vb-nczuy.js} +1 -1
- package/dist/compiler-ui/_not-found/__next._full.txt +10 -9
- package/dist/compiler-ui/_not-found/__next._head.txt +3 -3
- package/dist/compiler-ui/_not-found/__next._index.txt +5 -4
- package/dist/compiler-ui/_not-found/__next._not-found.__PAGE__.txt +2 -2
- package/dist/compiler-ui/_not-found/__next._not-found.txt +3 -3
- package/dist/compiler-ui/_not-found/__next._tree.txt +3 -2
- package/dist/compiler-ui/_not-found.html +1 -1
- package/dist/compiler-ui/_not-found.txt +10 -9
- package/dist/compiler-ui/index.html +1 -1
- package/dist/compiler-ui/index.txt +13 -12
- package/dist/packages/contracts/lib/schema.d.ts +4 -0
- package/dist/packages/contracts/lib/schema.js +2 -1
- package/dist/packages/engine/action-definitions.d.ts +174 -13
- package/dist/packages/engine/action-definitions.js +125 -122
- package/dist/packages/engine/action-planner.js +4 -11
- package/dist/packages/engine/agents/lib/shells.d.ts +3 -1
- package/dist/packages/engine/agents/lib/shells.js +8 -4
- package/dist/packages/engine/agents/role-executors.js +1 -1
- package/dist/packages/engine/compile/compiled-paths.js +6 -6
- package/dist/packages/engine/connection-config.js +1 -1
- package/dist/packages/engine/execution/lib/schema.d.ts +10 -0
- package/dist/packages/engine/instance-paths.d.ts +15 -9
- package/dist/packages/engine/instance-paths.js +15 -9
- package/dist/packages/engine/lib/schema.d.ts +686 -30
- package/dist/packages/engine/lib/schema.js +48 -21
- package/dist/packages/engine/native-run-handlers.js +10 -8
- package/dist/packages/engine/preparation-store.d.ts +9 -13
- package/dist/packages/engine/preparation-store.js +12 -0
- package/dist/packages/engine/requested-artifacts.d.ts +5 -0
- package/dist/packages/engine/requested-artifacts.js +36 -0
- package/dist/packages/engine/routes.d.ts +1 -1
- package/dist/packages/engine/routes.js +1 -1
- package/dist/packages/engine/run-observability.js +3 -2
- package/dist/packages/engine/runtime-proposal-helpers.d.ts +2 -2
- package/dist/packages/engine/runtime-proposal-helpers.js +5 -7
- package/dist/packages/engine/runtime-resource-builders.d.ts +5 -0
- package/dist/packages/engine/runtime-resource-builders.js +13 -2
- package/dist/packages/engine/runtime.d.ts +3 -1
- package/dist/packages/engine/runtime.js +146 -21
- package/dist/packages/engine/server.js +104 -52
- package/dist/packages/engine/verify/verify-execution.js +1 -1
- package/dist/packages/engine/wire-schemas.d.ts +5 -1
- package/dist/packages/engine/wire-schemas.js +1 -1
- package/dist/packages/methods/authoring/method-authoring.d.ts +3 -1
- package/dist/packages/methods/authoring/method-authoring.js +5 -36
- package/dist/packages/methods/package/builtin-compiled-method.js +1 -1
- package/dist/packages/methods/package/local-methods.d.ts +1 -0
- package/dist/packages/methods/package/local-methods.js +19 -4
- package/dist/packages/methods/package/method-definitions.js +1 -1
- package/dist/packages/project/interf-detect.js +6 -6
- package/dist/packages/project/lib/schema.d.ts +193 -0
- package/dist/packages/project/lib/schema.js +46 -1
- package/dist/packages/project/source-config.js +4 -0
- package/dist/packages/project/source-folders.js +1 -1
- package/package.json +7 -8
- package/public-repo/CONTRIBUTING.md +47 -0
- package/public-repo/LICENSE.md +1 -0
- package/public-repo/README.md +325 -0
- package/public-repo/SECURITY.md +67 -0
- package/public-repo/TRADEMARKS.md +8 -0
- package/{builtin-methods → public-repo/methods}/interf-default/README.md +4 -0
- package/{builtin-methods → public-repo/methods}/interf-default/compile/stages/shape/SKILL.md +4 -8
- package/{builtin-methods → public-repo/methods}/interf-default/method.json +1 -1
- package/public-repo/methods/interf-default/use/query/SKILL.md +23 -0
- package/public-repo/plugins/README.md +9 -0
- package/public-repo/plugins/interf/.claude-plugin/plugin.json +21 -0
- package/public-repo/plugins/interf/.mcp.json +12 -0
- package/public-repo/plugins/interf/README.md +29 -0
- package/public-repo/plugins/interf/skills/interf/SKILL.md +477 -0
- package/public-repo/skills/interf/SKILL.md +477 -0
- package/agent-skills/interf-actions/SKILL.md +0 -185
- package/agent-skills/interf-actions/references/cli.md +0 -243
- package/builtin-methods/interf-default/use/query/SKILL.md +0 -28
- package/dist/cli/commands/verify.d.ts +0 -10
- package/dist/compiler-ui/_next/static/chunks/06yhdspx~ca5-.js +0 -5
- package/dist/compiler-ui/_next/static/chunks/06z~l3kwb891e.js +0 -1
- package/dist/compiler-ui/_next/static/chunks/08g7lvje.te.u.js +0 -1
- package/dist/compiler-ui/_next/static/chunks/0_c_tvh-cukjz.css +0 -3
- package/dist/compiler-ui/_next/static/chunks/0_i-3_5l9t2qe.js +0 -1
- package/dist/compiler-ui/_next/static/chunks/0b-ywny_j0g~0.js +0 -1
- package/dist/compiler-ui/_next/static/chunks/0b52v41o1gixx.js +0 -1
- package/dist/compiler-ui/_next/static/chunks/0f_geuwdesg_c.js +0 -114
- package/dist/compiler-ui/_next/static/chunks/0gpzgsv0w.q~m.js +0 -31
- package/dist/compiler-ui/_next/static/chunks/0ilwfezfvu6~-.js +0 -1
- package/dist/compiler-ui/_next/static/chunks/0xxmf45eskdt~.css +0 -1
- package/dist/compiler-ui/_next/static/chunks/14wtz~vq25~qq.js +0 -1
- /package/dist/compiler-ui/_next/static/{6qyE1u9m_oBUkvAhhoCmO → tYHMLL9oKds1yDoNYgkPV}/_buildManifest.js +0 -0
- /package/dist/compiler-ui/_next/static/{6qyE1u9m_oBUkvAhhoCmO → tYHMLL9oKds1yDoNYgkPV}/_clientMiddlewareManifest.js +0 -0
- /package/dist/compiler-ui/_next/static/{6qyE1u9m_oBUkvAhhoCmO → tYHMLL9oKds1yDoNYgkPV}/_ssgManifest.js +0 -0
- /package/{builtin-methods → public-repo/methods}/interf-default/compile/stages/structure/SKILL.md +0 -0
- /package/{builtin-methods → public-repo/methods}/interf-default/compile/stages/summarize/SKILL.md +0 -0
- /package/{builtin-methods → public-repo/methods}/interf-default/improve/SKILL.md +0 -0
- /package/{builtin-methods → public-repo/methods}/interf-default/method.schema.json +0 -0
|
@@ -16,7 +16,7 @@ import { findSourcePreparationConfig, fingerprintReadinessChecks, listSourcePrep
|
|
|
16
16
|
import { listSourceFolderChoices, } from "../project/source-folders.js";
|
|
17
17
|
import { asPreparationDataDir, preparationPortableContextPath, userMethodsRoot, preparationConfigPath, preparationMethodPackagePath, preparationMethodsRoot, } from "../contracts/lib/preparation-paths.js";
|
|
18
18
|
import { getCompiledMethod, listCompiledMethodChoices, } from "../methods/package/method-definitions.js";
|
|
19
|
-
import { computeArtifactStatuses, } from "./compile/artifact-status.js";
|
|
19
|
+
import { aggregateArtifactVerdict, computeArtifactStatuses, } from "./compile/artifact-status.js";
|
|
20
20
|
import { JsonlBillingEventSink, buildCompilationEventsForRun, defaultBillingEventLogPath, } from "./compile/billing-events.js";
|
|
21
21
|
import { methodDefinitionPath, resolveMethodPackageSourcePath, } from "../methods/package/local-methods.js";
|
|
22
22
|
import { seedLocalMethodPackageFromBase, } from "../methods/package/interf-method-package.js";
|
|
@@ -30,14 +30,33 @@ import { ActionProposalApprovalRequestSchema, ActionProposalCreateRequestSchema,
|
|
|
30
30
|
import { buildLocalServiceUrl, } from "./routes.js";
|
|
31
31
|
import { MethodAuthoringActionValuesSchema, PreparationSetupActionValuesSchema, } from "./action-values.js";
|
|
32
32
|
import { compileRunToObservability, jobRunToObservability, verifyRunToObservability, uniqueArtifacts, } from "./run-observability.js";
|
|
33
|
+
import { artifactRequirementsFromRequestedArtifacts } from "./requested-artifacts.js";
|
|
33
34
|
/** TTL for `POST /v1/compile-runs` idempotency-key dedupe entries. */
|
|
34
35
|
const IDEMPOTENCY_TTL_MS = 60 * 60 * 1000;
|
|
35
36
|
/** Idempotency cache size at which to schedule an opportunistic prune. */
|
|
36
37
|
const IDEMPOTENCY_PRUNE_THRESHOLD = 64;
|
|
37
38
|
const INTERRUPTED_COMPILE_RUN_MESSAGE = "Compile run interrupted because the Interf engine stopped before the run reached a terminal state.";
|
|
39
|
+
const INTERRUPTED_JOB_RUN_MESSAGE = "Job interrupted because the Interf engine stopped before the job reached a terminal state.";
|
|
38
40
|
function isTerminalCompileRunStatus(status) {
|
|
39
41
|
return status === "succeeded" || status === "failed" || status === "cancelled";
|
|
40
42
|
}
|
|
43
|
+
function isTerminalJobStatus(status) {
|
|
44
|
+
return status === "succeeded" || status === "failed" || status === "cancelled";
|
|
45
|
+
}
|
|
46
|
+
function countsFromCompiledState(state) {
|
|
47
|
+
const counts = {};
|
|
48
|
+
for (const stage of Object.values(state.stages ?? {})) {
|
|
49
|
+
for (const [key, value] of Object.entries(stage.counts ?? {})) {
|
|
50
|
+
if (Number.isFinite(value))
|
|
51
|
+
counts[key] = Math.max(counts[key] ?? 0, value);
|
|
52
|
+
}
|
|
53
|
+
for (const [key, value] of Object.entries(stage.artifact_counts ?? {})) {
|
|
54
|
+
if (Number.isFinite(value))
|
|
55
|
+
counts[key] = Math.max(counts[key] ?? 0, value);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return counts;
|
|
59
|
+
}
|
|
41
60
|
export class LocalServiceRuntime {
|
|
42
61
|
host;
|
|
43
62
|
port;
|
|
@@ -173,6 +192,7 @@ export class LocalServiceRuntime {
|
|
|
173
192
|
};
|
|
174
193
|
this.preparationContexts.set(resolved, context);
|
|
175
194
|
this.finalizeInterruptedCompileRuns(resolved);
|
|
195
|
+
this.finalizeInterruptedJobRuns(resolved);
|
|
176
196
|
this.onRegistryChanged?.();
|
|
177
197
|
return context;
|
|
178
198
|
}
|
|
@@ -342,6 +362,13 @@ export class LocalServiceRuntime {
|
|
|
342
362
|
const compileRun = this.listCompileRunsForPreparation(prepDataDir, preparation.name)[0] ?? null;
|
|
343
363
|
const verifyRun = this.listVerifyRunsForPreparation(prepDataDir, preparation.name)[0] ?? null;
|
|
344
364
|
const readinessRun = this.readLatestReadinessRun(prepDataDir, preparation.name);
|
|
365
|
+
const artifactStatuses = compileRun?.artifacts ?? [];
|
|
366
|
+
const hasArtifactContract = artifactStatuses.length > 0;
|
|
367
|
+
const artifactVerdict = aggregateArtifactVerdict(artifactStatuses);
|
|
368
|
+
const artifactFailures = artifactStatuses.filter((artifact) => artifact.status !== "ready");
|
|
369
|
+
const artifactProofs = artifactStatuses.flatMap((artifact) => artifact.proofs ?? []);
|
|
370
|
+
const requiredArtifactProofs = artifactProofs.filter((proof) => proof.required !== false);
|
|
371
|
+
const passedArtifactProofs = requiredArtifactProofs.filter((proof) => proof.passed);
|
|
345
372
|
const configuredChecks = preparation.checks.length;
|
|
346
373
|
const currentFingerprint = configuredChecks > 0 ? fingerprintReadinessChecks(preparation.checks) : null;
|
|
347
374
|
const readinessRunFingerprint = readinessRun?.checks_fingerprint ?? null;
|
|
@@ -407,13 +434,25 @@ export class LocalServiceRuntime {
|
|
|
407
434
|
artifact_path: contextReady ? compiledPath : null,
|
|
408
435
|
},
|
|
409
436
|
compileCheck,
|
|
437
|
+
{
|
|
438
|
+
gate: "artifact-checks",
|
|
439
|
+
ok: !hasArtifactContract || artifactVerdict === "ready",
|
|
440
|
+
status: !hasArtifactContract
|
|
441
|
+
? "not-configured"
|
|
442
|
+
: artifactVerdict === "ready" ? "ready" : "not-ready",
|
|
443
|
+
summary: !hasArtifactContract
|
|
444
|
+
? "No Artifacts are declared by the selected Build Plan."
|
|
445
|
+
: artifactVerdict === "ready"
|
|
446
|
+
? `${artifactStatuses.length} Artifact${artifactStatuses.length === 1 ? "" : "s"} ready; ${passedArtifactProofs.length}/${requiredArtifactProofs.length} required Artifact check${requiredArtifactProofs.length === 1 ? "" : "s"} passed.`
|
|
447
|
+
: `${artifactFailures.length} Artifact${artifactFailures.length === 1 ? "" : "s"} not ready.`,
|
|
448
|
+
},
|
|
410
449
|
{
|
|
411
450
|
gate: "readiness-checks",
|
|
412
|
-
ok:
|
|
451
|
+
ok: true,
|
|
413
452
|
status: configuredChecks > 0 ? "built" : "not-configured",
|
|
414
453
|
summary: configuredChecks > 0
|
|
415
454
|
? `${configuredChecks} readiness check${configuredChecks === 1 ? "" : "s"} configured.`
|
|
416
|
-
: "No readiness checks are configured.",
|
|
455
|
+
: "No optional readiness checks are configured.",
|
|
417
456
|
},
|
|
418
457
|
{
|
|
419
458
|
gate: "checks-current",
|
|
@@ -433,10 +472,12 @@ export class LocalServiceRuntime {
|
|
|
433
472
|
return "failed";
|
|
434
473
|
if (!compileRun || !contextReady)
|
|
435
474
|
return "not-built";
|
|
436
|
-
if (
|
|
437
|
-
return "not-
|
|
475
|
+
if (hasArtifactContract && artifactVerdict !== "ready")
|
|
476
|
+
return "not-ready";
|
|
438
477
|
if (checksStale)
|
|
439
478
|
return "stale";
|
|
479
|
+
if (configuredChecks === 0)
|
|
480
|
+
return hasArtifactContract ? "ready" : "built";
|
|
440
481
|
if (!contextResult)
|
|
441
482
|
return "built";
|
|
442
483
|
return contextResult.total > 0 && contextResult.passed === contextResult.total ? "ready" : "not-ready";
|
|
@@ -535,7 +576,7 @@ export class LocalServiceRuntime {
|
|
|
535
576
|
// method roots. Key the cache off mtimes for the three roots; if
|
|
536
577
|
// any of them changes (a new local Method, an edit to the user
|
|
537
578
|
// library, etc.) the cache misses and we re-resolve.
|
|
538
|
-
const builtinRoot = join(PACKAGE_ROOT, "
|
|
579
|
+
const builtinRoot = join(PACKAGE_ROOT, "public-repo", "methods");
|
|
539
580
|
const localRoot = preparationMethodsRoot(asPreparationDataDir(prepDataDir));
|
|
540
581
|
const userRoot = userMethodsRoot();
|
|
541
582
|
return this.methodListingCache.get(prepDataDir, [builtinRoot, localRoot, userRoot], () => {
|
|
@@ -550,6 +591,8 @@ export class LocalServiceRuntime {
|
|
|
550
591
|
path: resolveMethodPackageSourcePath(prepDataDir, method.id) ?? method.id,
|
|
551
592
|
label: method.label,
|
|
552
593
|
hint: method.hint,
|
|
594
|
+
purpose: method.purpose,
|
|
595
|
+
inputs: method.inputs,
|
|
553
596
|
source_kind: method.scope === "builtin" ? "builtin" : "local",
|
|
554
597
|
built_in: method.scope === "builtin",
|
|
555
598
|
active_for_preparations: activeForPreparations,
|
|
@@ -754,7 +797,10 @@ export class LocalServiceRuntime {
|
|
|
754
797
|
}
|
|
755
798
|
listRunObservability(prepDataDir) {
|
|
756
799
|
return [
|
|
757
|
-
...this.listCompileRuns(prepDataDir).map((resource) => compileRunToObservability(
|
|
800
|
+
...this.listCompileRuns(prepDataDir).map((resource) => compileRunToObservability({
|
|
801
|
+
...resource.run,
|
|
802
|
+
readiness: this.getReadiness(prepDataDir, resource.run.preparation),
|
|
803
|
+
})),
|
|
758
804
|
...this.listVerifyRuns(prepDataDir).map(verifyRunToObservability),
|
|
759
805
|
...this.listJobs(prepDataDir).map(jobRunToObservability),
|
|
760
806
|
].sort((left, right) => {
|
|
@@ -767,7 +813,7 @@ export class LocalServiceRuntime {
|
|
|
767
813
|
return this.listRunObservability(prepDataDir).find((run) => run.run_id === runId) ?? null;
|
|
768
814
|
}
|
|
769
815
|
/**
|
|
770
|
-
* Method
|
|
816
|
+
* Method Activity runs: every method-authoring or method-improvement job
|
|
771
817
|
* whose `method` matches `methodId`. Surfaced through
|
|
772
818
|
* `GET /v1/methods/<id>/runs` so Method Detail can show the full audit
|
|
773
819
|
* trail of authoring + improvement work for a Method.
|
|
@@ -966,11 +1012,16 @@ export class LocalServiceRuntime {
|
|
|
966
1012
|
applyPreparationSetup(prepDataDir, requestValue) {
|
|
967
1013
|
const request = PreparationSetupCreateRequestSchema.parse(requestValue);
|
|
968
1014
|
const preparationConfig = request.preparation;
|
|
969
|
-
const methodId = methodIdForSourcePreparationConfig(preparationConfig)
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
1015
|
+
const methodId = methodIdForSourcePreparationConfig(preparationConfig);
|
|
1016
|
+
if (request.setup_mode === "select-method" && !methodId) {
|
|
1017
|
+
throw new Error("Build Plan is required when selecting a Build Plan for a Preparation.");
|
|
1018
|
+
}
|
|
1019
|
+
const normalizedPreparationConfig = methodId
|
|
1020
|
+
? { ...preparationConfig, method: methodId }
|
|
1021
|
+
: (() => {
|
|
1022
|
+
const { method: _method, ...withoutMethod } = preparationConfig;
|
|
1023
|
+
return withoutMethod;
|
|
1024
|
+
})();
|
|
974
1025
|
const sourceFolderPath = resolveSourcePreparationPath(prepDataDir, normalizedPreparationConfig);
|
|
975
1026
|
if (!existsSync(sourceFolderPath) || !statSync(sourceFolderPath).isDirectory()) {
|
|
976
1027
|
throw new Error(`Source folder "${preparationConfig.path}" is not available.`);
|
|
@@ -989,14 +1040,16 @@ export class LocalServiceRuntime {
|
|
|
989
1040
|
version: 1,
|
|
990
1041
|
operation,
|
|
991
1042
|
preparation: normalizedPreparationConfig.name,
|
|
992
|
-
method: methodId,
|
|
1043
|
+
method: methodId ?? null,
|
|
993
1044
|
source_folder_path: sourceFolderPath,
|
|
994
1045
|
config_path: preparationConfigPath(asPreparationDataDir(prepDataDir)),
|
|
995
1046
|
portable_context_path: preparationPortableContextPath(asPreparationDataDir(prepDataDir), normalizedPreparationConfig.name),
|
|
996
1047
|
changed: true,
|
|
997
1048
|
message: operation === "select-method"
|
|
998
|
-
? `Preparation ${normalizedPreparationConfig.name} now uses
|
|
999
|
-
:
|
|
1049
|
+
? `Preparation ${normalizedPreparationConfig.name} now uses Build Plan ${methodId}.`
|
|
1050
|
+
: methodId
|
|
1051
|
+
? `Preparation ${normalizedPreparationConfig.name} is saved with Build Plan ${methodId}.`
|
|
1052
|
+
: `Preparation ${normalizedPreparationConfig.name} is saved. Draft or select a Build Plan before compiling.`,
|
|
1000
1053
|
});
|
|
1001
1054
|
}
|
|
1002
1055
|
applyPreparationChange(prepDataDir, requestValue) {
|
|
@@ -1051,7 +1104,17 @@ export class LocalServiceRuntime {
|
|
|
1051
1104
|
});
|
|
1052
1105
|
}
|
|
1053
1106
|
async createMethodAuthoringRun(prepDataDir, requestValue, jobType = "method-authoring") {
|
|
1054
|
-
const
|
|
1107
|
+
const parsedRequest = MethodAuthoringCreateRequestSchema.parse(requestValue);
|
|
1108
|
+
const savedPreparation = parsedRequest.preparation
|
|
1109
|
+
? findSourcePreparationConfig(loadSourceFolderConfig(prepDataDir), parsedRequest.preparation)
|
|
1110
|
+
: null;
|
|
1111
|
+
const request = {
|
|
1112
|
+
...parsedRequest,
|
|
1113
|
+
requested_artifacts: parsedRequest.requested_artifacts.length > 0
|
|
1114
|
+
? parsedRequest.requested_artifacts
|
|
1115
|
+
: savedPreparation?.requested_artifacts ?? [],
|
|
1116
|
+
source_profile: parsedRequest.source_profile ?? savedPreparation?.source_profile ?? null,
|
|
1117
|
+
};
|
|
1055
1118
|
const isImprovement = jobType === "method-improvement";
|
|
1056
1119
|
const job = this.createJobRun(prepDataDir, {
|
|
1057
1120
|
job_type: jobType,
|
|
@@ -1068,6 +1131,7 @@ export class LocalServiceRuntime {
|
|
|
1068
1131
|
preparation: request.preparation ?? null,
|
|
1069
1132
|
source_folder_path: request.source_folder_path,
|
|
1070
1133
|
checks: request.checks.length,
|
|
1134
|
+
requested_artifacts: request.requested_artifacts.length,
|
|
1071
1135
|
},
|
|
1072
1136
|
},
|
|
1073
1137
|
{
|
|
@@ -1077,6 +1141,7 @@ export class LocalServiceRuntime {
|
|
|
1077
1141
|
method_id: request.method_id,
|
|
1078
1142
|
label: request.label,
|
|
1079
1143
|
task_prompt: request.task_prompt,
|
|
1144
|
+
requested_artifacts: request.requested_artifacts.length,
|
|
1080
1145
|
artifact_requirements: request.artifact_requirements.length,
|
|
1081
1146
|
},
|
|
1082
1147
|
},
|
|
@@ -1097,6 +1162,7 @@ export class LocalServiceRuntime {
|
|
|
1097
1162
|
preparation: request.preparation ?? null,
|
|
1098
1163
|
source_folder_path: request.source_folder_path,
|
|
1099
1164
|
checks: request.checks.length,
|
|
1165
|
+
requested_artifacts: request.requested_artifacts.length,
|
|
1100
1166
|
},
|
|
1101
1167
|
});
|
|
1102
1168
|
this.appendJobRunEvent(prepDataDir, job.run_id, {
|
|
@@ -1106,6 +1172,7 @@ export class LocalServiceRuntime {
|
|
|
1106
1172
|
output: {
|
|
1107
1173
|
source_folder_path: request.source_folder_path,
|
|
1108
1174
|
checks: request.checks.length,
|
|
1175
|
+
requested_artifacts: request.requested_artifacts.length,
|
|
1109
1176
|
},
|
|
1110
1177
|
});
|
|
1111
1178
|
this.appendJobRunEvent(prepDataDir, job.run_id, {
|
|
@@ -1116,6 +1183,7 @@ export class LocalServiceRuntime {
|
|
|
1116
1183
|
method_id: request.method_id,
|
|
1117
1184
|
label: request.label,
|
|
1118
1185
|
task_prompt: request.task_prompt,
|
|
1186
|
+
requested_artifacts: request.requested_artifacts.length,
|
|
1119
1187
|
artifact_requirements: request.artifact_requirements.length,
|
|
1120
1188
|
},
|
|
1121
1189
|
});
|
|
@@ -1157,7 +1225,7 @@ export class LocalServiceRuntime {
|
|
|
1157
1225
|
const compiledPath = preparationPortableContextPath(asPreparationDataDir(prepDataDir), preparationName);
|
|
1158
1226
|
return byCreatedAtDesc(listJsonFiles(compileRunsRoot(compiledPath))
|
|
1159
1227
|
.map(readCompileRunAt)
|
|
1160
|
-
.filter((run) => run !== null));
|
|
1228
|
+
.filter((run) => run !== null)).map((run) => this.hydrateCompileRunFromRuntime(prepDataDir, compiledPath, run));
|
|
1161
1229
|
}, (run) => run.run_id);
|
|
1162
1230
|
}
|
|
1163
1231
|
getCompileRun(prepDataDir, runId) {
|
|
@@ -1633,18 +1701,35 @@ export class LocalServiceRuntime {
|
|
|
1633
1701
|
},
|
|
1634
1702
|
});
|
|
1635
1703
|
if (result.status === "updated" || result.status === "no-change") {
|
|
1704
|
+
let selectedPreparation = null;
|
|
1705
|
+
if (request.preparation) {
|
|
1706
|
+
const selected = this.resolvePreparationConfig(prepDataDir, request.preparation, {
|
|
1707
|
+
method: request.method_id,
|
|
1708
|
+
});
|
|
1709
|
+
upsertSourcePreparationConfig(prepDataDir, selected);
|
|
1710
|
+
this.readinessCache.invalidatePreparation(prepDataDir, selected.name);
|
|
1711
|
+
this.compileRunCache.invalidatePreparation(prepDataDir, selected.name);
|
|
1712
|
+
this.verifyRunCache.invalidatePreparation(prepDataDir, selected.name);
|
|
1713
|
+
this.methodListingCache.invalidate(prepDataDir);
|
|
1714
|
+
selectedPreparation = selected.name;
|
|
1715
|
+
}
|
|
1636
1716
|
this.appendJobRunEvent(prepDataDir, runId, {
|
|
1637
1717
|
type: "step.completed",
|
|
1638
1718
|
step_id: "validate-package",
|
|
1639
|
-
message:
|
|
1719
|
+
message: selectedPreparation
|
|
1720
|
+
? `${result.summary} Selected Build Plan ${request.method_id} for Preparation ${selectedPreparation}.`
|
|
1721
|
+
: result.summary,
|
|
1640
1722
|
output: {
|
|
1641
1723
|
status: result.status,
|
|
1642
1724
|
validation: result.validation ?? null,
|
|
1725
|
+
selected_preparation: selectedPreparation,
|
|
1643
1726
|
},
|
|
1644
1727
|
});
|
|
1645
1728
|
this.appendJobRunEvent(prepDataDir, runId, {
|
|
1646
1729
|
type: "job.completed",
|
|
1647
|
-
message:
|
|
1730
|
+
message: selectedPreparation
|
|
1731
|
+
? `${result.summary} Selected Build Plan ${request.method_id} for Preparation ${selectedPreparation}.`
|
|
1732
|
+
: result.summary,
|
|
1648
1733
|
});
|
|
1649
1734
|
}
|
|
1650
1735
|
else {
|
|
@@ -1700,7 +1785,7 @@ export class LocalServiceRuntime {
|
|
|
1700
1785
|
return ActionProposalPlanSchema.parse({
|
|
1701
1786
|
action_type: "clarification",
|
|
1702
1787
|
...(request.preparation ? { preparation: request.preparation } : {}),
|
|
1703
|
-
assistant_message: "No local action planner is configured for this Interf
|
|
1788
|
+
assistant_message: "No local action planner is configured for this Interf instance.",
|
|
1704
1789
|
});
|
|
1705
1790
|
}
|
|
1706
1791
|
const preparations = listSourcePreparationConfigs(loadSourceFolderConfig(prepDataDir));
|
|
@@ -1885,6 +1970,9 @@ export class LocalServiceRuntime {
|
|
|
1885
1970
|
hint,
|
|
1886
1971
|
task_prompt: taskPrompt,
|
|
1887
1972
|
checks: preparationConfig?.checks ?? [],
|
|
1973
|
+
requested_artifacts: preparationConfig?.requested_artifacts ?? [],
|
|
1974
|
+
source_profile: preparationConfig?.source_profile ?? null,
|
|
1975
|
+
artifact_requirements: artifactRequirementsFromRequestedArtifacts(preparationConfig?.requested_artifacts ?? []),
|
|
1888
1976
|
};
|
|
1889
1977
|
const commandPreview = (usePlannerText ? plan.command_preview : undefined) ??
|
|
1890
1978
|
actionCommandPreview(actionType, preparationConfig?.name ?? null, methodId, proposalValues);
|
|
@@ -2002,6 +2090,9 @@ export class LocalServiceRuntime {
|
|
|
2002
2090
|
hint,
|
|
2003
2091
|
task_prompt: taskPrompt,
|
|
2004
2092
|
checks: preparationConfig.checks ?? [],
|
|
2093
|
+
requested_artifacts: preparationConfig.requested_artifacts ?? [],
|
|
2094
|
+
source_profile: preparationConfig.source_profile ?? null,
|
|
2095
|
+
artifact_requirements: artifactRequirementsFromRequestedArtifacts(preparationConfig.requested_artifacts ?? []),
|
|
2005
2096
|
};
|
|
2006
2097
|
})();
|
|
2007
2098
|
const title = (() => {
|
|
@@ -2108,6 +2199,12 @@ export class LocalServiceRuntime {
|
|
|
2108
2199
|
readCompileRun(compiledPath, runId) {
|
|
2109
2200
|
return readCompileRunAt(compileRunPath(compiledPath, runId));
|
|
2110
2201
|
}
|
|
2202
|
+
hydrateCompileRunFromRuntime(prepDataDir, compiledPath, run) {
|
|
2203
|
+
if (!isTerminalCompileRunStatus(run.status))
|
|
2204
|
+
return run;
|
|
2205
|
+
this.refreshCompileRunFromRuntime(prepDataDir, compiledPath, run.run_id);
|
|
2206
|
+
return this.readCompileRun(compiledPath, run.run_id) ?? run;
|
|
2207
|
+
}
|
|
2111
2208
|
finalizeInterruptedCompileRuns(prepDataDir) {
|
|
2112
2209
|
let preparations;
|
|
2113
2210
|
try {
|
|
@@ -2148,6 +2245,33 @@ export class LocalServiceRuntime {
|
|
|
2148
2245
|
}
|
|
2149
2246
|
}
|
|
2150
2247
|
}
|
|
2248
|
+
finalizeInterruptedJobRuns(prepDataDir) {
|
|
2249
|
+
for (const run of this.listJobs(prepDataDir)) {
|
|
2250
|
+
if (isTerminalJobStatus(run.status))
|
|
2251
|
+
continue;
|
|
2252
|
+
const timestamp = createRunEventTimestamp();
|
|
2253
|
+
const interruptedRun = LocalJobRunResourceSchema.parse({
|
|
2254
|
+
...run,
|
|
2255
|
+
steps: run.steps.map((step) => {
|
|
2256
|
+
if (step.status !== "running")
|
|
2257
|
+
return step;
|
|
2258
|
+
return {
|
|
2259
|
+
...step,
|
|
2260
|
+
status: "failed",
|
|
2261
|
+
finished_at: step.finished_at ?? timestamp,
|
|
2262
|
+
summary: step.summary ?? INTERRUPTED_JOB_RUN_MESSAGE,
|
|
2263
|
+
};
|
|
2264
|
+
}),
|
|
2265
|
+
});
|
|
2266
|
+
this.writeJobRun(prepDataDir, applyEventToLocalJob(interruptedRun, {
|
|
2267
|
+
type: "job.failed",
|
|
2268
|
+
event_id: createRunEventId("event"),
|
|
2269
|
+
run_id: run.run_id,
|
|
2270
|
+
timestamp,
|
|
2271
|
+
message: INTERRUPTED_JOB_RUN_MESSAGE,
|
|
2272
|
+
}));
|
|
2273
|
+
}
|
|
2274
|
+
}
|
|
2151
2275
|
/**
|
|
2152
2276
|
* 0.17 — emit per-Artifact billing events when a compile run reaches
|
|
2153
2277
|
* a terminal state. STUB FORM: writes a JSONL file alongside the run
|
|
@@ -2281,6 +2405,7 @@ export class LocalServiceRuntime {
|
|
|
2281
2405
|
method,
|
|
2282
2406
|
compiledPath,
|
|
2283
2407
|
stageRuns: next.stages,
|
|
2408
|
+
counts: countsFromCompiledState(state),
|
|
2284
2409
|
});
|
|
2285
2410
|
}
|
|
2286
2411
|
catch {
|
|
@@ -4,7 +4,7 @@ import { randomBytes } from "node:crypto";
|
|
|
4
4
|
import { existsSync, statSync, readFileSync } from "node:fs";
|
|
5
5
|
import { dirname, extname, join, normalize, resolve, sep } from "node:path";
|
|
6
6
|
import { fileURLToPath } from "node:url";
|
|
7
|
-
import { LOCAL_SERVICE_LOOPBACK_HOSTS, LocalServiceConfigSchema, LocalServiceDiscoverySchema, LocalServiceErrorSchema, OpenPathRequestSchema, ServiceRegistryEntrySchema, } from "./lib/schema.js";
|
|
7
|
+
import { LOCAL_SERVICE_LOOPBACK_HOSTS, LocalServiceConfigSchema, LocalServiceDiscoverySchema, LocalServiceErrorSchema, OpenPathRequestSchema, PreparationCreateRequestSchema, PreparationUpdateRequestSchema, ServiceRegistryEntrySchema, } from "./lib/schema.js";
|
|
8
8
|
import { assertPathWithinRoot, } from "../contracts/utils/path-guards.js";
|
|
9
9
|
import { createLocalServiceRuntime, } from "./runtime.js";
|
|
10
10
|
import { buildLocalServiceUrl, LOCAL_SERVICE_DEFAULT_HOST, LOCAL_SERVICE_DEFAULT_PORT, LOCAL_SERVICE_ROUTES, PREPARATION_SUBRESOURCES, } from "./routes.js";
|
|
@@ -124,7 +124,7 @@ function packageRoot() {
|
|
|
124
124
|
}
|
|
125
125
|
export function resolveCompilerUiStaticRoot(rootPath = packageRoot()) {
|
|
126
126
|
const distRoot = join(rootPath, "dist", "compiler-ui");
|
|
127
|
-
const sourceExportRoot = join(rootPath, "apps", "compiler-ui", "out");
|
|
127
|
+
const sourceExportRoot = join(rootPath, "src", "apps", "compiler-ui", "out");
|
|
128
128
|
if (existsSync(join(distRoot, "index.html")))
|
|
129
129
|
return distRoot;
|
|
130
130
|
if (existsSync(join(sourceExportRoot, "index.html")))
|
|
@@ -384,6 +384,78 @@ async function routeApi(req, res, runtime) {
|
|
|
384
384
|
const method = req.method ?? "GET";
|
|
385
385
|
const origin = originHeaderValue(req);
|
|
386
386
|
const allowed = buildAllowedOrigins(runtime.host, runtime.port);
|
|
387
|
+
const prepDataDirsForInstance = () => {
|
|
388
|
+
const dirs = listStoredPreparations().map((prep) => prep.prepDataDir);
|
|
389
|
+
return dirs.length > 0 ? dirs : [runtime.rootPath];
|
|
390
|
+
};
|
|
391
|
+
const listInstanceRuns = () => {
|
|
392
|
+
return prepDataDirsForInstance()
|
|
393
|
+
.flatMap((prepDataDir) => runtime.listRunObservability(prepDataDir))
|
|
394
|
+
.sort((left, right) => {
|
|
395
|
+
const leftMs = Date.parse(left.started_at ?? left.created_at ?? left.finished_at ?? "");
|
|
396
|
+
const rightMs = Date.parse(right.started_at ?? right.created_at ?? right.finished_at ?? "");
|
|
397
|
+
return (Number.isFinite(rightMs) ? rightMs : 0) - (Number.isFinite(leftMs) ? leftMs : 0);
|
|
398
|
+
});
|
|
399
|
+
};
|
|
400
|
+
const findInstanceRun = (runId) => {
|
|
401
|
+
for (const prepDataDir of prepDataDirsForInstance()) {
|
|
402
|
+
const run = runtime.getRunObservability(prepDataDir, runId);
|
|
403
|
+
if (run)
|
|
404
|
+
return run;
|
|
405
|
+
}
|
|
406
|
+
return null;
|
|
407
|
+
};
|
|
408
|
+
const findInstanceJob = (runId) => {
|
|
409
|
+
for (const prepDataDir of prepDataDirsForInstance()) {
|
|
410
|
+
const job = runtime.getJob(prepDataDir, runId);
|
|
411
|
+
if (job)
|
|
412
|
+
return { job, prepDataDir };
|
|
413
|
+
}
|
|
414
|
+
return null;
|
|
415
|
+
};
|
|
416
|
+
const listInstanceMethods = () => {
|
|
417
|
+
const byId = new Map();
|
|
418
|
+
for (const prepDataDir of prepDataDirsForInstance()) {
|
|
419
|
+
for (const methodResource of runtime.listMethods(prepDataDir)) {
|
|
420
|
+
const existing = byId.get(methodResource.id);
|
|
421
|
+
if (!existing) {
|
|
422
|
+
byId.set(methodResource.id, methodResource);
|
|
423
|
+
continue;
|
|
424
|
+
}
|
|
425
|
+
const preferred = existing.built_in && !methodResource.built_in
|
|
426
|
+
? methodResource
|
|
427
|
+
: existing;
|
|
428
|
+
byId.set(methodResource.id, {
|
|
429
|
+
...preferred,
|
|
430
|
+
active_for_preparations: Array.from(new Set([
|
|
431
|
+
...existing.active_for_preparations,
|
|
432
|
+
...methodResource.active_for_preparations,
|
|
433
|
+
])).sort(),
|
|
434
|
+
});
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
return [...byId.values()].sort((left, right) => left.id.localeCompare(right.id));
|
|
438
|
+
};
|
|
439
|
+
const findInstanceMethod = (methodId) => {
|
|
440
|
+
return listInstanceMethods().find((methodResource) => methodResource.id === methodId) ?? null;
|
|
441
|
+
};
|
|
442
|
+
const listInstanceMethodRuns = (methodId) => {
|
|
443
|
+
return prepDataDirsForInstance()
|
|
444
|
+
.flatMap((prepDataDir) => runtime.listMethodRuns(prepDataDir, methodId))
|
|
445
|
+
.sort((left, right) => {
|
|
446
|
+
const leftMs = Date.parse(left.started_at ?? left.created_at ?? left.finished_at ?? "");
|
|
447
|
+
const rightMs = Date.parse(right.started_at ?? right.created_at ?? right.finished_at ?? "");
|
|
448
|
+
return (Number.isFinite(rightMs) ? rightMs : 0) - (Number.isFinite(leftMs) ? leftMs : 0);
|
|
449
|
+
});
|
|
450
|
+
};
|
|
451
|
+
const resolveInstanceMethodPackageRoot = (methodId) => {
|
|
452
|
+
for (const prepDataDir of prepDataDirsForInstance()) {
|
|
453
|
+
const localPath = methodDefinitionPath(prepDataDir, methodId);
|
|
454
|
+
if (existsSync(join(localPath, "method.json")))
|
|
455
|
+
return localPath;
|
|
456
|
+
}
|
|
457
|
+
return resolveMethodPackageRoot(methodId);
|
|
458
|
+
};
|
|
387
459
|
// CORS preflight — answered for allowed origins, refused otherwise.
|
|
388
460
|
if (method === "OPTIONS") {
|
|
389
461
|
if (!isOriginAllowed(origin, allowed)) {
|
|
@@ -489,32 +561,15 @@ async function routeApi(req, res, runtime) {
|
|
|
489
561
|
// POST /v1/preparations — create a new preparation.
|
|
490
562
|
if (method === "POST" && path === LOCAL_SERVICE_ROUTES.preparations) {
|
|
491
563
|
try {
|
|
492
|
-
const body = (await readJsonBody(req));
|
|
493
|
-
if (!body || typeof body !== "object") {
|
|
494
|
-
sendError(res, 400, "Request body must be a JSON object.");
|
|
495
|
-
return true;
|
|
496
|
-
}
|
|
497
|
-
if (!body.id || typeof body.id !== "string") {
|
|
498
|
-
sendError(res, 400, "Missing required field: id");
|
|
499
|
-
return true;
|
|
500
|
-
}
|
|
501
|
-
if (!body.method_id || typeof body.method_id !== "string") {
|
|
502
|
-
sendError(res, 400, "Missing required field: method_id");
|
|
503
|
-
return true;
|
|
504
|
-
}
|
|
505
|
-
if (!body.source || typeof body.source !== "object" || !body.source.locator) {
|
|
506
|
-
sendError(res, 400, "Missing required field: source.locator");
|
|
507
|
-
return true;
|
|
508
|
-
}
|
|
564
|
+
const body = PreparationCreateRequestSchema.parse(await readJsonBody(req));
|
|
509
565
|
// TODO(cloud): activate remote-folder validator branch when the
|
|
510
566
|
// cloud variant lands. The local binary only knows how to read
|
|
511
567
|
// bytes from a local path; a `remote-folder` binding requires
|
|
512
568
|
// the cloud variant's per-account object-storage mount layer.
|
|
513
569
|
// Until then, reject any kind other than `local-folder` so the
|
|
514
570
|
// wire shape and runtime stay consistent.
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
sendError(res, 400, `Unsupported source kind: ${requestedKind}. The local engine only accepts local-folder bindings; remote-folder requires the cloud variant.`);
|
|
571
|
+
if (body.source.kind !== "local-folder") {
|
|
572
|
+
sendError(res, 400, `Unsupported source kind: ${body.source.kind}. The local engine only accepts local-folder bindings; remote-folder requires the cloud variant.`);
|
|
518
573
|
return true;
|
|
519
574
|
}
|
|
520
575
|
const stored = createStoredPreparation(runtime, {
|
|
@@ -522,6 +577,8 @@ async function routeApi(req, res, runtime) {
|
|
|
522
577
|
source: { kind: "local-folder", locator: body.source.locator },
|
|
523
578
|
method_id: body.method_id,
|
|
524
579
|
about: body.about,
|
|
580
|
+
requested_artifacts: body.requested_artifacts,
|
|
581
|
+
source_profile: body.source_profile,
|
|
525
582
|
checks: body.checks,
|
|
526
583
|
max_attempts: body.max_attempts,
|
|
527
584
|
max_loops: body.max_loops,
|
|
@@ -551,20 +608,26 @@ async function routeApi(req, res, runtime) {
|
|
|
551
608
|
if (subPath === "") {
|
|
552
609
|
// Bare /v1/preparations/{id}
|
|
553
610
|
if (method === "GET") {
|
|
554
|
-
|
|
611
|
+
const preparation = runtime.getPreparation(storedPrep.prepDataDir, storedPrep.id);
|
|
612
|
+
sendJson(res, 200, preparation
|
|
613
|
+
? {
|
|
614
|
+
...preparation,
|
|
615
|
+
source: storedPrep.source,
|
|
616
|
+
about: storedPrep.about,
|
|
617
|
+
config_path: storedPrep.configPath,
|
|
618
|
+
}
|
|
619
|
+
: preparationWireShape(storedPrep));
|
|
555
620
|
return true;
|
|
556
621
|
}
|
|
557
622
|
if (method === "PATCH") {
|
|
558
623
|
try {
|
|
559
|
-
const body = (await readJsonBody(req));
|
|
560
|
-
if (!body || typeof body !== "object") {
|
|
561
|
-
sendError(res, 400, "Request body must be a JSON object.");
|
|
562
|
-
return true;
|
|
563
|
-
}
|
|
624
|
+
const body = PreparationUpdateRequestSchema.parse(await readJsonBody(req));
|
|
564
625
|
const updated = updateStoredPreparation(decodedPrepId, {
|
|
565
626
|
method_id: body.method_id,
|
|
566
627
|
about: body.about,
|
|
567
628
|
...(body.checks !== undefined ? { checks: body.checks } : {}),
|
|
629
|
+
...(body.requested_artifacts !== undefined ? { requested_artifacts: body.requested_artifacts } : {}),
|
|
630
|
+
...(body.source_profile !== undefined ? { source_profile: body.source_profile } : {}),
|
|
568
631
|
});
|
|
569
632
|
sendJson(res, 200, preparationWireShape(updated));
|
|
570
633
|
}
|
|
@@ -582,7 +645,7 @@ async function routeApi(req, res, runtime) {
|
|
|
582
645
|
else if (subPath === PREPARATION_SUBRESOURCES.compileRuns) {
|
|
583
646
|
if (method === "POST") {
|
|
584
647
|
if (!storedPrep.methodId) {
|
|
585
|
-
sendError(res, 400, `Preparation ${storedPrep.id} has no
|
|
648
|
+
sendError(res, 400, `Preparation ${storedPrep.id} has no Build Plan selected. Select one via PATCH /v1/preparations/${storedPrep.id} { "method_id": "<id>" } before compiling.`);
|
|
586
649
|
return true;
|
|
587
650
|
}
|
|
588
651
|
try {
|
|
@@ -618,7 +681,7 @@ async function routeApi(req, res, runtime) {
|
|
|
618
681
|
else if (subPath === PREPARATION_SUBRESOURCES.verifyRuns) {
|
|
619
682
|
if (method === "POST") {
|
|
620
683
|
if (!storedPrep.methodId) {
|
|
621
|
-
sendError(res, 400, `Preparation ${storedPrep.id} has no
|
|
684
|
+
sendError(res, 400, `Preparation ${storedPrep.id} has no Build Plan selected. Select one via PATCH /v1/preparations/${storedPrep.id} { "method_id": "<id>" } before verifying.`);
|
|
622
685
|
return true;
|
|
623
686
|
}
|
|
624
687
|
try {
|
|
@@ -789,17 +852,12 @@ async function routeApi(req, res, runtime) {
|
|
|
789
852
|
// Method resources — preparation-independent (workspace draft + user lib + bundled).
|
|
790
853
|
// ─────────────────────────────────────────────────────────────────────────
|
|
791
854
|
if (method === "GET" && path === LOCAL_SERVICE_ROUTES.methods) {
|
|
792
|
-
|
|
793
|
-
// Fall back to the first registered preparation (if any) so user-library
|
|
794
|
-
// and bundled methods still surface even when no preparation has drafts.
|
|
795
|
-
const firstPrep = listStoredPreparations()[0];
|
|
796
|
-
sendJson(res, 200, { methods: runtime.listMethods(firstPrep?.prepDataDir ?? runtime.rootPath) });
|
|
855
|
+
sendJson(res, 200, { methods: listInstanceMethods() });
|
|
797
856
|
return true;
|
|
798
857
|
}
|
|
799
858
|
const methodMatch = path.match(/^\/v1\/methods\/([^/]+)$/);
|
|
800
859
|
if (method === "GET" && methodMatch?.[1]) {
|
|
801
|
-
const
|
|
802
|
-
const methodResource = runtime.getMethod(firstPrep?.prepDataDir ?? runtime.rootPath, decodeURIComponent(methodMatch[1]));
|
|
860
|
+
const methodResource = findInstanceMethod(decodeURIComponent(methodMatch[1]));
|
|
803
861
|
if (!methodResource)
|
|
804
862
|
sendError(res, 404, "Method not found.");
|
|
805
863
|
else
|
|
@@ -808,8 +866,7 @@ async function routeApi(req, res, runtime) {
|
|
|
808
866
|
}
|
|
809
867
|
const methodRunsMatch = path.match(/^\/v1\/methods\/([^/]+)\/runs$/);
|
|
810
868
|
if (method === "GET" && methodRunsMatch?.[1]) {
|
|
811
|
-
const
|
|
812
|
-
const runs = runtime.listMethodRuns(firstPrep?.prepDataDir ?? runtime.rootPath, decodeURIComponent(methodRunsMatch[1]));
|
|
869
|
+
const runs = listInstanceMethodRuns(decodeURIComponent(methodRunsMatch[1]));
|
|
813
870
|
sendJson(res, 200, { runs });
|
|
814
871
|
return true;
|
|
815
872
|
}
|
|
@@ -834,8 +891,7 @@ async function routeApi(req, res, runtime) {
|
|
|
834
891
|
sendError(res, 400, "File path escapes method root.");
|
|
835
892
|
return true;
|
|
836
893
|
}
|
|
837
|
-
const
|
|
838
|
-
const root = resolveMethodPackageRoot(methodId, firstPrep?.prepDataDir);
|
|
894
|
+
const root = resolveInstanceMethodPackageRoot(methodId);
|
|
839
895
|
if (!root) {
|
|
840
896
|
sendError(res, 404, `Method not found: ${methodId}`);
|
|
841
897
|
return true;
|
|
@@ -855,14 +911,12 @@ async function routeApi(req, res, runtime) {
|
|
|
855
911
|
// so the runtime takes a "first prep" hint to scan registered preparations.
|
|
856
912
|
// ─────────────────────────────────────────────────────────────────────────
|
|
857
913
|
if (method === "GET" && path === LOCAL_SERVICE_ROUTES.runs) {
|
|
858
|
-
|
|
859
|
-
sendJson(res, 200, { runs: runtime.listRunObservability(firstPrep?.prepDataDir ?? runtime.rootPath) });
|
|
914
|
+
sendJson(res, 200, { runs: listInstanceRuns() });
|
|
860
915
|
return true;
|
|
861
916
|
}
|
|
862
917
|
const observableRunMatch = path.match(/^\/v1\/runs\/([^/]+)$/);
|
|
863
918
|
if (method === "GET" && observableRunMatch?.[1]) {
|
|
864
|
-
const
|
|
865
|
-
const run = runtime.getRunObservability(firstPrep?.prepDataDir ?? runtime.rootPath, decodeURIComponent(observableRunMatch[1]));
|
|
919
|
+
const run = findInstanceRun(decodeURIComponent(observableRunMatch[1]));
|
|
866
920
|
if (!run)
|
|
867
921
|
sendError(res, 404, "Run not found.");
|
|
868
922
|
else
|
|
@@ -975,18 +1029,16 @@ async function routeApi(req, res, runtime) {
|
|
|
975
1029
|
if (jobMatch?.[1]) {
|
|
976
1030
|
const runId = decodeURIComponent(jobMatch[1]);
|
|
977
1031
|
const child = jobMatch[2];
|
|
978
|
-
const
|
|
979
|
-
const prepDataDir = firstPrep?.prepDataDir ?? runtime.rootPath;
|
|
1032
|
+
const found = findInstanceJob(runId);
|
|
980
1033
|
if (method === "GET" && !child) {
|
|
981
|
-
|
|
982
|
-
if (!job)
|
|
1034
|
+
if (!found)
|
|
983
1035
|
sendError(res, 404, "Job run not found.");
|
|
984
1036
|
else
|
|
985
|
-
sendJson(res, 200, job);
|
|
1037
|
+
sendJson(res, 200, found.job);
|
|
986
1038
|
return true;
|
|
987
1039
|
}
|
|
988
1040
|
if (method === "GET" && child === "events") {
|
|
989
|
-
const events = runtime.getJobEvents(prepDataDir, runId);
|
|
1041
|
+
const events = found ? runtime.getJobEvents(found.prepDataDir, runId) : null;
|
|
990
1042
|
if (!events)
|
|
991
1043
|
sendError(res, 404, "Job run not found.");
|
|
992
1044
|
else
|
|
@@ -1118,7 +1170,7 @@ async function routeApi(req, res, runtime) {
|
|
|
1118
1170
|
allowedRoots.push(stored.source.locator);
|
|
1119
1171
|
}
|
|
1120
1172
|
allowedRoots.push(userMethodsRoot());
|
|
1121
|
-
allowedRoots.push(packageRoot()); // covers <pkg>/
|
|
1173
|
+
allowedRoots.push(packageRoot()); // covers <pkg>/public-repo/methods/...
|
|
1122
1174
|
const openedPath = await openLocalPath(allowedRoots, body.path);
|
|
1123
1175
|
sendJson(res, 202, { opened: true, path: openedPath });
|
|
1124
1176
|
return true;
|
|
@@ -203,7 +203,7 @@ function buildTestQueryPrompt(target, testCase, answerPath, tracePath) {
|
|
|
203
203
|
"Answer the check question the same way you would answer a real user inside this portable context.",
|
|
204
204
|
"Prefer the Method-declared portable-context outputs before consulting source references.",
|
|
205
205
|
"This sandbox is self-contained: the copied portable context has source references in `.interf/runtime/source-snapshot.json`.",
|
|
206
|
-
"The original Interf
|
|
206
|
+
"The original Interf instance state is intentionally absent from this sandbox. Use the source locators only when the portable context needs verification.",
|
|
207
207
|
]
|
|
208
208
|
: [
|
|
209
209
|
"You are running an Interf baseline test inside an isolated source-files test shell.",
|