@kontextmind/kxm 0.7.130 → 0.7.132
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/.claude-plugin/marketplace.json +1 -1
- package/.kxm/README.md +4 -1
- package/.kxm/agents/coordinator.yaml +1 -0
- package/.kxm/agents/critic-arch.yaml +1 -4
- package/.kxm/agents/critic-cli.yaml +1 -4
- package/.kxm/agents/implementer.yaml +1 -4
- package/.kxm/workflows/implement-only.yaml +1 -1
- package/.kxm/workflows/review-arch-only.yaml +1 -1
- package/.kxm/workflows/review-cli-only.yaml +1 -1
- package/CHANGELOG.md +22 -1
- package/docs/concepts/architecture.md +1 -1
- package/docs/contracts/routing.md +3 -3
- package/docs/contributing/assignment-runner.md +14 -15
- package/docs/contributing/development.md +19 -5
- package/docs/contributing/harness-routing-internals.md +8 -8
- package/docs/glossary.md +1 -1
- package/docs/guides/agent-skills.md +1 -1
- package/docs/operations/backup-and-restore.md +4 -4
- package/docs/reference/cli-reference.md +26 -8
- package/docs/reference/config-reference.md +76 -153
- package/docs/reference/harness-routing.md +29 -21
- package/docs/reference/workflow-catalog.md +4 -4
- package/docs/start/first-workflow.md +1 -1
- package/examples/project/.kxm/agents/coordinator.yaml +1 -2
- package/examples/project/.kxm/agents/critic-1.yaml +1 -3
- package/examples/project/.kxm/agents/critic-2.yaml +1 -2
- package/examples/project/.kxm/agents/critic-3.yaml +2 -3
- package/examples/project/.kxm/agents/implementer.yaml +1 -2
- package/examples/project/.kxm/agents/planner.yaml +1 -2
- package/examples/project/.kxm/agents/reproducer.yaml +1 -2
- package/examples/project/.kxm/agents/reviewer.yaml +1 -2
- package/examples/project/.kxm/workflows/fix.yaml +0 -12
- package/package.json +1 -1
- package/plugins/kxm/.claude-plugin/plugin.json +1 -1
- package/plugins/kxm/dist/cli.js +287 -249
- package/plugins/kxm/dist/mcp-server.js +1 -1
- package/plugins/kxm/dist/runtime-supervisor.js +222 -242
- package/plugins/kxm/dist/runtime.js +224 -244
- package/plugins/kxm/package.json +1 -1
- package/plugins/kxm/skills/kxm/SKILL.md +1 -1
- package/plugins/kxm/skills/kxm-definitions/SKILL.md +8 -0
- package/plugins/kxm/src/cli/project.ts +4 -4
- package/plugins/kxm/src/engine.ts +168 -163
- package/plugins/kxm/src/init-guide-setup.ts +75 -15
- package/plugins/kxm/src/mcp-server.ts +1 -1
- package/plugins/kxm/src/oneshot-producer.ts +3 -15
- package/plugins/kxm/src/project-config.ts +83 -70
- package/plugins/kxm/src/routes.ts +26 -18
- package/plugins/kxm/src/runtime-supervisor.ts +0 -18
- package/plugins/kxm/src/suggest.ts +2 -2
- package/plugins/kxm/src/template.ts +2 -14
- package/schemas/agent.schema.json +8 -0
- package/scripts/roster-policy.d.mts +2 -1
- package/scripts/roster-policy.mjs +119 -22
|
@@ -15663,21 +15663,9 @@ function coreTemplate(projectId, projectName, variant) {
|
|
|
15663
15663
|
]);
|
|
15664
15664
|
if (variant === "v4-registry") {
|
|
15665
15665
|
const coordinator = files.get(".kxm/agents/coordinator.yaml");
|
|
15666
|
-
if (coordinator) {
|
|
15667
|
-
files.set(".kxm/agents/coordinator.yaml", {
|
|
15668
|
-
...coordinator,
|
|
15669
|
-
harness: "claude",
|
|
15670
|
-
model: { provider: "anthropic", model: "fable" }
|
|
15671
|
-
});
|
|
15672
|
-
}
|
|
15666
|
+
if (coordinator) files.set(".kxm/agents/coordinator.yaml", { ...coordinator, role: "planner" });
|
|
15673
15667
|
const implementer = files.get(".kxm/agents/implementer.yaml");
|
|
15674
|
-
if (implementer) {
|
|
15675
|
-
files.set(".kxm/agents/implementer.yaml", {
|
|
15676
|
-
...implementer,
|
|
15677
|
-
harness: "grok",
|
|
15678
|
-
model: { provider: "xai", model: "grok-4.6" }
|
|
15679
|
-
});
|
|
15680
|
-
}
|
|
15668
|
+
if (implementer) files.set(".kxm/agents/implementer.yaml", { ...implementer, role: "writer" });
|
|
15681
15669
|
const workflow = files.get(".kxm/workflows/default.yaml");
|
|
15682
15670
|
if (workflow) {
|
|
15683
15671
|
const limits = { ...workflow.limits };
|
|
@@ -17316,7 +17304,7 @@ function readTemplateProvenance(registry, root) {
|
|
|
17316
17304
|
}
|
|
17317
17305
|
return value;
|
|
17318
17306
|
}
|
|
17319
|
-
function listNamedResources(registry, root, directory, logicalDirectory, kind, replacedId) {
|
|
17307
|
+
function listNamedResources(registry, root, directory, logicalDirectory, kind, replacedId, collected) {
|
|
17320
17308
|
const resources = /* @__PURE__ */ new Map();
|
|
17321
17309
|
if (!existsSync3(directory)) return resources;
|
|
17322
17310
|
const stat = lstatSync(directory);
|
|
@@ -17355,7 +17343,10 @@ function listNamedResources(registry, root, directory, logicalDirectory, kind, r
|
|
|
17355
17343
|
else throw error;
|
|
17356
17344
|
}
|
|
17357
17345
|
}
|
|
17358
|
-
if (issues.length > 0)
|
|
17346
|
+
if (issues.length > 0) {
|
|
17347
|
+
if (collected) collected.push(...issues);
|
|
17348
|
+
else throw new KxmConfigError(issues);
|
|
17349
|
+
}
|
|
17359
17350
|
return resources;
|
|
17360
17351
|
}
|
|
17361
17352
|
function valuesOf(object, field) {
|
|
@@ -17619,6 +17610,9 @@ function validateWorkflow(workflow, agents, models, repositories, gates, issues)
|
|
|
17619
17610
|
for (const repositoryId of Object.keys(objectValue(step.repositories) ?? {})) {
|
|
17620
17611
|
if (!repositories.has(repositoryId)) issues.push(issue3("reference", "repository_unknown", file, `${stepId} references unknown repository ${repositoryId}`));
|
|
17621
17612
|
}
|
|
17613
|
+
if ((kind === "agent" || kind === "moa") && step.model !== void 0) {
|
|
17614
|
+
issues.push(issue3("semantic", "producer_route_unsupported", file, `${stepId} model is not honored; remove model from the step`));
|
|
17615
|
+
}
|
|
17622
17616
|
selectorCandidates(step.model, models, file, `${stepId}.model`, issues);
|
|
17623
17617
|
const assignment = objectValue(step.assignments);
|
|
17624
17618
|
const declaredAgents = assignment ? names(assignment.allowedAgents) : [];
|
|
@@ -17801,7 +17795,7 @@ function validateModelReferences(models, issues) {
|
|
|
17801
17795
|
};
|
|
17802
17796
|
for (const id of models.keys()) walk(id, []);
|
|
17803
17797
|
}
|
|
17804
|
-
function validateBundle(project, repositories, agents, models, workflows, environments, options, gateRegistry, projectRoot,
|
|
17798
|
+
function validateBundle(project, repositories, agents, models, workflows, environments, options, gateRegistry, projectRoot, roles = /* @__PURE__ */ new Map()) {
|
|
17805
17799
|
const issues = [];
|
|
17806
17800
|
const entries = valuesOf(project.value, "repositories").map((candidate) => objectValue(candidate)).filter((candidate) => Boolean(candidate));
|
|
17807
17801
|
const repositoryIds = /* @__PURE__ */ new Set();
|
|
@@ -17842,84 +17836,84 @@ function validateBundle(project, repositories, agents, models, workflows, enviro
|
|
|
17842
17836
|
const defaultHarness = stringValue(project.value.defaultHarness) ?? DEFAULT_HARNESS;
|
|
17843
17837
|
if (!harnesses.has(defaultHarness)) issues.push(issue3("reference", "harness_unknown", project.logicalPath, `defaultHarness ${defaultHarness} is not registered`));
|
|
17844
17838
|
for (const agent of agents.values()) {
|
|
17839
|
+
if (agent.value.model !== void 0 || agent.value.harness !== void 0) {
|
|
17840
|
+
issues.push(issue3("semantic", "retired_agent_routing_fields", agent.logicalPath, "routing resolves from role; remove model and harness"));
|
|
17841
|
+
}
|
|
17845
17842
|
validateToolPolicy(agent, objectValue(agent.value.tools), "tools", issues);
|
|
17846
17843
|
const executor = stringValue(agent.value.executor);
|
|
17847
17844
|
if (executor && !executors.has(executor)) issues.push(issue3("reference", "executor_unknown", agent.logicalPath, `executor ${executor} is not registered`));
|
|
17848
|
-
const harness = stringValue(agent.value.harness) ?? defaultHarness;
|
|
17849
|
-
if (!harnesses.has(harness)) issues.push(issue3("reference", "harness_unknown", agent.logicalPath, `harness ${harness} is not registered`));
|
|
17850
17845
|
const preset = stringValue(objectValue(agent.value.tools)?.preset);
|
|
17851
17846
|
if (preset && !presets.has(preset)) issues.push(issue3("reference", "tool_preset_unknown", agent.logicalPath, `tool preset ${preset} is not registered`));
|
|
17852
17847
|
for (const repositoryId of Object.keys(objectValue(agent.value.repositories) ?? {})) {
|
|
17853
17848
|
if (!repositoryIds.has(repositoryId)) issues.push(issue3("reference", "repository_unknown", agent.logicalPath, `references unknown repository ${repositoryId}`));
|
|
17854
17849
|
}
|
|
17855
|
-
const candidates = selectorCandidates(agent.value.model, models, agent.logicalPath, "model", issues);
|
|
17856
|
-
const declaredHarness = stringValue(agent.value.harness);
|
|
17857
|
-
if (declaredHarness && harnesses.has(declaredHarness)) {
|
|
17858
|
-
for (const candidate of candidates) {
|
|
17859
|
-
const candidateProvider = stringValue(candidate.value.provider);
|
|
17860
|
-
const candidateModel = stringValue(candidate.value.model);
|
|
17861
|
-
const validation = validateHarnessModelPair(declaredHarness, { provider: candidateProvider, model: candidateModel });
|
|
17862
|
-
if (!validation.valid) {
|
|
17863
|
-
issues.push(issue3("semantic", validation.issue ?? "harness_unhosted_model", agent.logicalPath, validation.message ?? `harness ${declaredHarness} cannot host model ${candidateModel ?? candidate.logicalPath}`));
|
|
17864
|
-
}
|
|
17865
|
-
}
|
|
17866
|
-
}
|
|
17867
17850
|
}
|
|
17868
17851
|
validateModelReferences(models, issues);
|
|
17869
17852
|
const defaultWorkflow = stringValue(project.value.defaultWorkflow) ?? "default";
|
|
17870
17853
|
if (!workflows.has(defaultWorkflow)) issues.push(issue3("reference", "default_workflow_unknown", project.logicalPath, `default workflow ${defaultWorkflow} does not exist`));
|
|
17871
17854
|
for (const workflow of workflows.values()) validateWorkflow(workflow, agents, models, repositoryIds, gates, issues);
|
|
17855
|
+
if (projectRoot && existsSync3(join2(projectRoot, ".kxm", "roster.yaml"))) {
|
|
17856
|
+
issues.push(issue3("semantic", "retired_roster_file", ".kxm/roster.yaml", "create the role and model files and delete roster.yaml"));
|
|
17857
|
+
}
|
|
17858
|
+
if (projectRoot && existsSync3(join2(projectRoot, ".kxm", "roles"))) {
|
|
17859
|
+
issues.push(...developerRolePolicyIssues(projectRoot));
|
|
17860
|
+
}
|
|
17872
17861
|
if (projectRoot) {
|
|
17873
|
-
|
|
17874
|
-
|
|
17875
|
-
|
|
17862
|
+
issues.push(...rosterModelIssues(projectRoot, roles));
|
|
17863
|
+
issues.push(...originHashIssues(projectRoot, models));
|
|
17864
|
+
}
|
|
17865
|
+
return sortIssues3(issues);
|
|
17866
|
+
}
|
|
17867
|
+
function rosterModelIssues(projectRoot, roles) {
|
|
17868
|
+
const issues = [];
|
|
17869
|
+
for (const role of roles.values()) {
|
|
17870
|
+
for (const entry of valuesOf(role.value, "roster")) {
|
|
17871
|
+
const route = stringValue(objectValue(entry)?.route);
|
|
17872
|
+
if (!route) continue;
|
|
17873
|
+
const logical = `.kxm/models/${route}.yaml`;
|
|
17874
|
+
const file = join2(projectRoot, ".kxm", "models", `${route}.yaml`);
|
|
17875
|
+
let harness;
|
|
17876
17876
|
try {
|
|
17877
|
-
|
|
17878
|
-
|
|
17879
|
-
|
|
17880
|
-
|
|
17881
|
-
|
|
17882
|
-
|
|
17883
|
-
const named = direct ? [direct] : [];
|
|
17884
|
-
if (route) {
|
|
17885
|
-
const modelFile = join2(projectRoot, ".kxm", "models", `${route}.yaml`);
|
|
17886
|
-
if (existsSync3(modelFile)) {
|
|
17887
|
-
try {
|
|
17888
|
-
const modelDoc = objectValue(parseRestrictedYaml2(readFileSync(modelFile, "utf8"), modelFile));
|
|
17889
|
-
const model = modelDoc ? stringValue(modelDoc.model) : void 0;
|
|
17890
|
-
const vendor = modelDoc ? stringValue(modelDoc.vendor) : void 0;
|
|
17891
|
-
const harness = modelDoc ? stringValue(modelDoc.harness) : void 0;
|
|
17892
|
-
if (model) named.push(model);
|
|
17893
|
-
if (vendor && model) named.push(`${vendor}/${model}`);
|
|
17894
|
-
if (harness && model) named.push(`${harness}/${model}`);
|
|
17895
|
-
} catch {
|
|
17896
|
-
}
|
|
17897
|
-
}
|
|
17898
|
-
}
|
|
17899
|
-
return named;
|
|
17900
|
-
});
|
|
17901
|
-
const agentModelObj = objectValue(implementerAgent.value.model);
|
|
17902
|
-
const agentModelStr = stringValue(implementerAgent.value.model);
|
|
17903
|
-
const agentProvider = agentModelObj ? stringValue(agentModelObj.provider) : void 0;
|
|
17904
|
-
const agentModel = agentModelObj ? stringValue(agentModelObj.model) : agentModelStr;
|
|
17905
|
-
const canonicalAgentModel = agentProvider && agentModel ? `${agentProvider}/${agentModel}` : agentModel;
|
|
17906
|
-
if (enabledRosterModels.length > 0 && canonicalAgentModel) {
|
|
17907
|
-
const matches = enabledRosterModels.some((rm) => rm === canonicalAgentModel || rm === agentModel || rm.endsWith(`/${agentModel}`));
|
|
17908
|
-
if (!matches) {
|
|
17909
|
-
issues.push(issue3("semantic", "role_roster_conflicts_with_agent", ".kxm/roles/writer.yaml", `role roster in .kxm/roles/writer.yaml does not include agent model ${canonicalAgentModel} from ${implementerAgent.logicalPath}`));
|
|
17910
|
-
}
|
|
17911
|
-
}
|
|
17912
|
-
} catch (error) {
|
|
17913
|
-
if (error instanceof KxmConfigError) {
|
|
17914
|
-
issues.push(...error.issues);
|
|
17915
|
-
}
|
|
17877
|
+
if (existsSync3(file)) harness = stringValue(parseRestrictedYaml2(readFileSync(file, "utf8"), logical).harness);
|
|
17878
|
+
} catch {
|
|
17879
|
+
harness = void 0;
|
|
17880
|
+
}
|
|
17881
|
+
if (!harness) {
|
|
17882
|
+
issues.push(issue3("semantic", "roster_model_unreadable", role.logicalPath, `roster route ${route} does not resolve to a readable ${logical} carrying harness`));
|
|
17916
17883
|
}
|
|
17917
17884
|
}
|
|
17918
17885
|
}
|
|
17919
|
-
|
|
17920
|
-
|
|
17886
|
+
return issues;
|
|
17887
|
+
}
|
|
17888
|
+
function originHashIssues(projectRoot, models) {
|
|
17889
|
+
const issues = [];
|
|
17890
|
+
for (const model of models.values()) {
|
|
17891
|
+
const origin = objectValue(model.value.origin);
|
|
17892
|
+
const source = origin ? stringValue(origin.source) : void 0;
|
|
17893
|
+
const digest2 = origin ? stringValue(origin.sha256) : void 0;
|
|
17894
|
+
if (!source || !digest2) continue;
|
|
17895
|
+
const file = resolve(projectRoot, source);
|
|
17896
|
+
const escaped = relative(projectRoot, file);
|
|
17897
|
+
if (isAbsolute(source) || escaped.startsWith("..") || isAbsolute(escaped)) {
|
|
17898
|
+
issues.push(issue3("semantic", "origin_evidence_missing", model.logicalPath, `missing evidence bytes for ${source}`));
|
|
17899
|
+
continue;
|
|
17900
|
+
}
|
|
17901
|
+
let actual;
|
|
17902
|
+
try {
|
|
17903
|
+
actual = createHash3("sha256").update(readFileSync(file, "utf8"), "utf8").digest("hex");
|
|
17904
|
+
} catch (error) {
|
|
17905
|
+
const code = error.code;
|
|
17906
|
+
if (code === "ENOENT" || code === "EACCES" || code === "EPERM" || code === "EISDIR") {
|
|
17907
|
+
issues.push(issue3("semantic", "origin_evidence_missing", model.logicalPath, `missing evidence bytes for ${source}`));
|
|
17908
|
+
continue;
|
|
17909
|
+
}
|
|
17910
|
+
throw error;
|
|
17911
|
+
}
|
|
17912
|
+
if (actual !== digest2) {
|
|
17913
|
+
issues.push(issue3("semantic", "origin_hash_mismatch", model.logicalPath, "origin evidence hash does not match supplied bytes"));
|
|
17914
|
+
}
|
|
17921
17915
|
}
|
|
17922
|
-
return
|
|
17916
|
+
return issues;
|
|
17923
17917
|
}
|
|
17924
17918
|
function developerCeilings() {
|
|
17925
17919
|
const script = join2(findKxmRepoRoot(import.meta.url), "scripts", "harness-run.mjs");
|
|
@@ -17948,6 +17942,7 @@ function developerCeilings() {
|
|
|
17948
17942
|
}
|
|
17949
17943
|
}
|
|
17950
17944
|
function developerRolePolicyIssues(projectRoot) {
|
|
17945
|
+
if (resolve(projectRoot) !== findKxmRepoRoot(import.meta.url)) return [];
|
|
17951
17946
|
const rolesDir = join2(projectRoot, ".kxm", "roles");
|
|
17952
17947
|
const modelsDir = join2(projectRoot, ".kxm", "models");
|
|
17953
17948
|
const roles = {};
|
|
@@ -17968,6 +17963,7 @@ function developerRolePolicyIssues(projectRoot) {
|
|
|
17968
17963
|
parseIssues.push(...error.issues);
|
|
17969
17964
|
continue;
|
|
17970
17965
|
}
|
|
17966
|
+
throw error;
|
|
17971
17967
|
}
|
|
17972
17968
|
}
|
|
17973
17969
|
};
|
|
@@ -17982,7 +17978,7 @@ function developerRolePolicyIssues(projectRoot) {
|
|
|
17982
17978
|
}
|
|
17983
17979
|
const ceilings = developerCeilings();
|
|
17984
17980
|
if (!ceilings.ok) {
|
|
17985
|
-
return [...parseIssues, issue3("semantic", "developer_ceilings_unavailable", ".kxm/
|
|
17981
|
+
return [...parseIssues, issue3("semantic", "developer_ceilings_unavailable", ".kxm/models", `developer ceilings could not be loaded: ${ceilings.detail}`)];
|
|
17986
17982
|
}
|
|
17987
17983
|
const result = validatePolicyDraft({ models, roles, evidence }, {
|
|
17988
17984
|
ceilings: ceilings.ROUTES,
|
|
@@ -18071,7 +18067,8 @@ function loadProjectBundle(projectRoot, options, candidate) {
|
|
|
18071
18067
|
}
|
|
18072
18068
|
if (earlyIssues.length > 0) throw new KxmConfigError(earlyIssues);
|
|
18073
18069
|
const agents = listNamedResources(registry, root, join2(root, ".kxm", "agents"), ".kxm/agents", "agent");
|
|
18074
|
-
const
|
|
18070
|
+
const modelIssues = [];
|
|
18071
|
+
const models = listNamedResources(registry, root, join2(root, ".kxm", "models"), ".kxm/models", "model", void 0, modelIssues);
|
|
18075
18072
|
const roles = listNamedResources(registry, root, join2(root, ".kxm", "roles"), ".kxm/roles", "role", writerRole === void 0 ? void 0 : "writer");
|
|
18076
18073
|
if (writerRole !== void 0) {
|
|
18077
18074
|
const logicalPath = ".kxm/roles/writer.yaml";
|
|
@@ -18198,8 +18195,8 @@ function loadProjectBundle(projectRoot, options, candidate) {
|
|
|
18198
18195
|
}
|
|
18199
18196
|
}
|
|
18200
18197
|
}
|
|
18201
|
-
if (loadIssues.length > 0) throw new KxmConfigError(loadIssues);
|
|
18202
|
-
const issues = validateBundle(project, repositories, agents, models, workflows, environments, options, gateRegistry, root,
|
|
18198
|
+
if (loadIssues.length > 0) throw new KxmConfigError([...loadIssues, ...modelIssues]);
|
|
18199
|
+
const issues = [...modelIssues, ...validateBundle(project, repositories, agents, models, workflows, environments, options, gateRegistry, root, roles)];
|
|
18203
18200
|
if (issues.length > 0) throw new KxmConfigError(issues);
|
|
18204
18201
|
const resources = [project, ...repositories.values(), ...agents.values(), ...models.values(), ...roles.values(), ...workflows.values(), ...environments, ...gateRegistry ? [gateRegistry] : []].sort((left, right) => compareCodeUnits4(left.logicalPath, right.logicalPath));
|
|
18205
18202
|
return {
|
|
@@ -24479,14 +24476,14 @@ var import_yaml4 = __toESM(require_dist(), 1);
|
|
|
24479
24476
|
|
|
24480
24477
|
// plugins/kxm/src/routes.ts
|
|
24481
24478
|
var RETIRED_POLICY = ".kxm/producers.yaml";
|
|
24482
|
-
var empty = () => ({ schema: "kxm.routes.v2", updatedAt: (/* @__PURE__ */ new Date()).toISOString(), admitted: [], disabled: []
|
|
24479
|
+
var empty = () => ({ schema: "kxm.routes.v2", updatedAt: (/* @__PURE__ */ new Date()).toISOString(), admitted: [], disabled: [] });
|
|
24483
24480
|
function loadRoutePolicy(root) {
|
|
24484
24481
|
if (existsSync9(join10(root, RETIRED_POLICY))) throw new Error(`retired ${RETIRED_POLICY} present; use .kxm/routes.yaml (kxm.routes.v2)`);
|
|
24485
24482
|
const path = join10(root, ".kxm", "routes.yaml");
|
|
24486
24483
|
if (!existsSync9(path)) return empty();
|
|
24487
24484
|
const value = (0, import_yaml6.parse)(readFileSync7(path, "utf8"));
|
|
24488
24485
|
if (value?.schema !== "kxm.routes.v2" || !Array.isArray(value.admitted)) throw new Error("invalid .kxm/routes.yaml");
|
|
24489
|
-
return { schema: "kxm.routes.v2", updatedAt: typeof value.updatedAt === "string" ? value.updatedAt : (/* @__PURE__ */ new Date()).toISOString(), admitted: value.admitted.filter((x) => typeof x === "string"), disabled: Array.isArray(value.disabled) ? value.disabled.filter((x) => typeof x === "string") : []
|
|
24486
|
+
return { schema: "kxm.routes.v2", updatedAt: typeof value.updatedAt === "string" ? value.updatedAt : (/* @__PURE__ */ new Date()).toISOString(), admitted: value.admitted.filter((x) => typeof x === "string"), disabled: Array.isArray(value.disabled) ? value.disabled.filter((x) => typeof x === "string") : [] };
|
|
24490
24487
|
}
|
|
24491
24488
|
function listRoleBindings(root) {
|
|
24492
24489
|
const dir = join10(root, ".kxm", "roles");
|
|
@@ -24499,10 +24496,6 @@ function listRoleBindings(root) {
|
|
|
24499
24496
|
}
|
|
24500
24497
|
return result;
|
|
24501
24498
|
}
|
|
24502
|
-
function isRouteAdmitted(root, modelId) {
|
|
24503
|
-
const policy = loadRoutePolicy(root);
|
|
24504
|
-
return policy.admitted.includes(modelId) && !policy.disabled.includes(modelId);
|
|
24505
|
-
}
|
|
24506
24499
|
|
|
24507
24500
|
// plugins/kxm/src/worktree-witness.ts
|
|
24508
24501
|
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
@@ -28070,25 +28063,18 @@ function commitCommandUncertainty(context, prepared, token, reason, observation,
|
|
|
28070
28063
|
}
|
|
28071
28064
|
}
|
|
28072
28065
|
var kxmPanelDispatchSeams = {};
|
|
28073
|
-
function
|
|
28074
|
-
|
|
28075
|
-
|
|
28076
|
-
|
|
28077
|
-
|
|
28078
|
-
|
|
28079
|
-
|
|
28080
|
-
|
|
28081
|
-
|
|
28082
|
-
|
|
28083
|
-
|
|
28084
|
-
const model = typeof parsed.model === "string" ? parsed.model : "";
|
|
28085
|
-
const vendor = typeof parsed.vendor === "string" ? parsed.vendor : "";
|
|
28086
|
-
const harness = typeof parsed.harness === "string" ? parsed.harness : "";
|
|
28087
|
-
if (model) selectors.add(model);
|
|
28088
|
-
if (vendor && model) selectors.add(`${vendor}/${model}`);
|
|
28089
|
-
if (harness && model) selectors.add(`${harness}/${model}`);
|
|
28066
|
+
function readYamlFile(file) {
|
|
28067
|
+
return readModelDocument(file);
|
|
28068
|
+
}
|
|
28069
|
+
function readModelDocument(file) {
|
|
28070
|
+
if (!existsSync12(file)) return void 0;
|
|
28071
|
+
try {
|
|
28072
|
+
const parsed = (0, import_yaml9.parse)(readFileSync10(file, "utf8"));
|
|
28073
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return void 0;
|
|
28074
|
+
return parsed;
|
|
28075
|
+
} catch {
|
|
28076
|
+
return void 0;
|
|
28090
28077
|
}
|
|
28091
|
-
return [...selectors];
|
|
28092
28078
|
}
|
|
28093
28079
|
function unreconciledPanelAttemptId(state) {
|
|
28094
28080
|
const current = state.currentStep;
|
|
@@ -28105,82 +28091,118 @@ function unreconciledPanelAttemptId(state) {
|
|
|
28105
28091
|
return void 0;
|
|
28106
28092
|
}
|
|
28107
28093
|
function resolveProducerRoute(projectRoot, step, agentId) {
|
|
28108
|
-
|
|
28109
|
-
const agentFile = join15(projectRoot, ".kxm", "agents", `${agentId}.yaml`);
|
|
28110
|
-
if (existsSync12(agentFile)) {
|
|
28111
|
-
try {
|
|
28112
|
-
const parsed = (0, import_yaml9.parse)(readFileSync10(agentFile, "utf8"));
|
|
28113
|
-
if (typeof parsed?.model === "string") {
|
|
28114
|
-
agentModel = parsed.model;
|
|
28115
|
-
} else if (parsed?.model && typeof parsed.model === "object" && !Array.isArray(parsed.model)) {
|
|
28116
|
-
const declared = parsed.model;
|
|
28117
|
-
const providerOk = typeof declared.provider === "string" && declared.provider.length > 0 && !declared.provider.includes("/");
|
|
28118
|
-
const modelOk = typeof declared.model === "string" && declared.model.length > 0 && !declared.model.startsWith("/") && !declared.model.endsWith("/");
|
|
28119
|
-
if (providerOk && modelOk) {
|
|
28120
|
-
agentModel = `${declared.provider}/${declared.model}`;
|
|
28121
|
-
} else {
|
|
28122
|
-
return {
|
|
28123
|
-
error: {
|
|
28124
|
-
reason: "step_unsupported",
|
|
28125
|
-
field: "model",
|
|
28126
|
-
detail: "producer_route_unsupported: invalid model declaration"
|
|
28127
|
-
}
|
|
28128
|
-
};
|
|
28129
|
-
}
|
|
28130
|
-
}
|
|
28131
|
-
} catch {
|
|
28132
|
-
}
|
|
28133
|
-
}
|
|
28134
|
-
let selector = typeof step.model === "string" ? step.model : agentModel;
|
|
28135
|
-
if (!selector) {
|
|
28136
|
-
if (agentId === "implementer") {
|
|
28137
|
-
selector = "xai/grok-4.6";
|
|
28138
|
-
}
|
|
28139
|
-
}
|
|
28140
|
-
if (!selector) {
|
|
28094
|
+
if ((step.kind === "agent" || step.kind === "moa") && step.model !== void 0) {
|
|
28141
28095
|
return {
|
|
28142
28096
|
error: {
|
|
28143
28097
|
reason: "step_unsupported",
|
|
28144
28098
|
field: "model",
|
|
28145
|
-
detail: "producer_route_unsupported: agent
|
|
28099
|
+
detail: "producer_route_unsupported: agent step model is not honored"
|
|
28146
28100
|
}
|
|
28147
28101
|
};
|
|
28148
28102
|
}
|
|
28149
|
-
const
|
|
28150
|
-
|
|
28103
|
+
const agent = readYamlFile(join15(projectRoot, ".kxm", "agents", `${agentId}.yaml`));
|
|
28104
|
+
const role = typeof agent?.role === "string" ? agent.role : "";
|
|
28105
|
+
if (!role) {
|
|
28151
28106
|
return {
|
|
28152
28107
|
error: {
|
|
28153
28108
|
reason: "step_unsupported",
|
|
28154
28109
|
field: "model",
|
|
28155
|
-
detail:
|
|
28110
|
+
detail: "producer_route_unsupported: agent has no role"
|
|
28156
28111
|
}
|
|
28157
28112
|
};
|
|
28158
28113
|
}
|
|
28159
|
-
|
|
28114
|
+
const roleDoc = readYamlFile(join15(projectRoot, ".kxm", "roles", `${role}.yaml`));
|
|
28115
|
+
const roster = Array.isArray(roleDoc?.roster) ? roleDoc.roster : void 0;
|
|
28116
|
+
if (!roster) {
|
|
28160
28117
|
return {
|
|
28161
28118
|
error: {
|
|
28162
28119
|
reason: "step_unsupported",
|
|
28163
28120
|
field: "model",
|
|
28164
|
-
detail: `producer_route_unsupported:
|
|
28121
|
+
detail: `producer_route_unsupported: role '${role}' has no roster`
|
|
28165
28122
|
}
|
|
28166
28123
|
};
|
|
28167
28124
|
}
|
|
28168
|
-
const
|
|
28169
|
-
const
|
|
28170
|
-
|
|
28171
|
-
|
|
28172
|
-
|
|
28125
|
+
const policy = loadRoutePolicy(projectRoot);
|
|
28126
|
+
for (const entry of roster) {
|
|
28127
|
+
if (!entry || typeof entry !== "object" || Array.isArray(entry)) continue;
|
|
28128
|
+
const record2 = entry;
|
|
28129
|
+
if (typeof record2.route !== "string" || record2.route.length === 0) continue;
|
|
28130
|
+
const modelPath = join15(projectRoot, ".kxm", "models", `${record2.route}.yaml`);
|
|
28131
|
+
const doc = readModelDocument(modelPath);
|
|
28132
|
+
if (!doc) {
|
|
28133
|
+
return {
|
|
28134
|
+
error: {
|
|
28135
|
+
reason: "step_unsupported",
|
|
28136
|
+
field: "model",
|
|
28137
|
+
detail: `producer_route_unsupported: model file '.kxm/models/${record2.route}.yaml' is missing or unreadable`
|
|
28138
|
+
}
|
|
28139
|
+
};
|
|
28140
|
+
}
|
|
28141
|
+
if (doc.status !== "admitted") continue;
|
|
28142
|
+
const modelName = typeof doc.model === "string" ? doc.model : "";
|
|
28143
|
+
const vendor = typeof doc.vendor === "string" ? doc.vendor : "";
|
|
28144
|
+
const harness = typeof doc.harness === "string" ? doc.harness : "";
|
|
28145
|
+
if (!modelName || !vendor || !harness) continue;
|
|
28146
|
+
const candidates = [modelName, `${vendor}/${modelName}`, `${harness}/${modelName}`];
|
|
28147
|
+
const admittedSelector = candidates.find((candidate) => policy.admitted.includes(candidate));
|
|
28148
|
+
const disabledSelector = candidates.find((candidate) => policy.disabled.includes(candidate));
|
|
28149
|
+
if (!admittedSelector && disabledSelector) {
|
|
28150
|
+
return {
|
|
28151
|
+
error: {
|
|
28152
|
+
reason: "step_unsupported",
|
|
28153
|
+
field: "model",
|
|
28154
|
+
detail: `producer_route_unsupported: first admitted route '${record2.route}' for role '${role}' is disabled`
|
|
28155
|
+
}
|
|
28156
|
+
};
|
|
28157
|
+
}
|
|
28158
|
+
const selector = admittedSelector ?? (modelName.includes("/") ? modelName : `${vendor}/${modelName}`);
|
|
28159
|
+
if (policy.disabled.includes(selector)) {
|
|
28160
|
+
return {
|
|
28161
|
+
error: {
|
|
28162
|
+
reason: "step_unsupported",
|
|
28163
|
+
field: "model",
|
|
28164
|
+
detail: `producer_route_unsupported: first admitted route '${record2.route}' for role '${role}' is disabled`
|
|
28165
|
+
}
|
|
28166
|
+
};
|
|
28167
|
+
}
|
|
28168
|
+
if (!policy.admitted.includes(selector)) {
|
|
28169
|
+
return {
|
|
28170
|
+
error: {
|
|
28171
|
+
reason: "step_unsupported",
|
|
28172
|
+
field: "model",
|
|
28173
|
+
detail: `producer_route_unsupported: model '${selector}' is not admitted`
|
|
28174
|
+
}
|
|
28175
|
+
};
|
|
28176
|
+
}
|
|
28177
|
+
const slash = selector.indexOf("/");
|
|
28178
|
+
if (slash <= 0 || slash === selector.length - 1) {
|
|
28179
|
+
return {
|
|
28180
|
+
error: {
|
|
28181
|
+
reason: "step_unsupported",
|
|
28182
|
+
field: "model",
|
|
28183
|
+
detail: `producer_route_unsupported: invalid selector '${selector}'`
|
|
28184
|
+
}
|
|
28185
|
+
};
|
|
28186
|
+
}
|
|
28187
|
+
const permissions = Array.isArray(doc.permissions) ? doc.permissions.filter((item) => typeof item === "string") : [];
|
|
28173
28188
|
return {
|
|
28174
|
-
|
|
28175
|
-
|
|
28176
|
-
|
|
28177
|
-
|
|
28178
|
-
|
|
28189
|
+
provider: selector.slice(0, slash),
|
|
28190
|
+
model: selector.slice(slash + 1),
|
|
28191
|
+
selector,
|
|
28192
|
+
harness,
|
|
28193
|
+
routeId: record2.route,
|
|
28194
|
+
role,
|
|
28195
|
+
permissions,
|
|
28196
|
+
...typeof record2.effort === "string" ? { effort: record2.effort } : {}
|
|
28179
28197
|
};
|
|
28180
28198
|
}
|
|
28181
|
-
|
|
28182
|
-
|
|
28183
|
-
|
|
28199
|
+
return {
|
|
28200
|
+
error: {
|
|
28201
|
+
reason: "step_unsupported",
|
|
28202
|
+
field: "model",
|
|
28203
|
+
detail: `producer_route_unsupported: role '${role}' has no admitted route`
|
|
28204
|
+
}
|
|
28205
|
+
};
|
|
28184
28206
|
}
|
|
28185
28207
|
function projectAgentStepTimeoutMs(context, run) {
|
|
28186
28208
|
return loadKxmRunPlanEnvelope(context.eventStore, run).projectLimits.agentStepTimeoutMs ?? KXM_DEFAULT_AGENT_STEP_TIMEOUT_MS;
|
|
@@ -28398,8 +28420,7 @@ function prepareDispatch(context, runId, producerId, dispatchSources) {
|
|
|
28398
28420
|
const writeRefusal = unsupportedLiveWrite(
|
|
28399
28421
|
context.projectRoot,
|
|
28400
28422
|
step,
|
|
28401
|
-
|
|
28402
|
-
resolvedRoute.selector,
|
|
28423
|
+
resolvedRoute,
|
|
28403
28424
|
loadKxmRunPlanEnvelope(context.eventStore, run).projectLimits.maxConcurrentRuns
|
|
28404
28425
|
);
|
|
28405
28426
|
if (writeRefusal) return { kind: "return", state, handoff: { ...writeRefusal, stepId } };
|
|
@@ -28428,7 +28449,7 @@ function prepareDispatch(context, runId, producerId, dispatchSources) {
|
|
|
28428
28449
|
for (const event of events) context.eventStore.appendEvent(event);
|
|
28429
28450
|
const entered = foldStoredKxmRun(context, run);
|
|
28430
28451
|
persistKxmRunState(context, runId, entered, events[events.length - 1].sequence);
|
|
28431
|
-
const
|
|
28452
|
+
const firstBirth = birthMember(context, {
|
|
28432
28453
|
run,
|
|
28433
28454
|
plan,
|
|
28434
28455
|
step,
|
|
@@ -28439,6 +28460,10 @@ function prepareDispatch(context, runId, producerId, dispatchSources) {
|
|
|
28439
28460
|
resolvedRoute,
|
|
28440
28461
|
dispatchSources
|
|
28441
28462
|
});
|
|
28463
|
+
if ("handoff" in firstBirth) {
|
|
28464
|
+
return { kind: "return", state: entered, handoff: firstBirth.handoff };
|
|
28465
|
+
}
|
|
28466
|
+
const first = firstBirth;
|
|
28442
28467
|
return {
|
|
28443
28468
|
kind: "panel",
|
|
28444
28469
|
panel: {
|
|
@@ -28501,9 +28526,10 @@ function birthMember(context, input) {
|
|
|
28501
28526
|
let resolvedRoute = input.resolvedRoute;
|
|
28502
28527
|
if (!resolvedRoute && input.producerId && input.producerId !== "driver-simulated") {
|
|
28503
28528
|
const routeResult = resolveProducerRoute(context.projectRoot, input.step, agentId);
|
|
28504
|
-
if (
|
|
28505
|
-
|
|
28529
|
+
if ("error" in routeResult) {
|
|
28530
|
+
return { handoff: { ...routeResult.error, stepId: input.stepId } };
|
|
28506
28531
|
}
|
|
28532
|
+
resolvedRoute = routeResult;
|
|
28507
28533
|
}
|
|
28508
28534
|
const dispatchContext = assembleDispatchContext(input.dispatchSources, {
|
|
28509
28535
|
projectId: run.projectId,
|
|
@@ -28610,11 +28636,11 @@ function birthMember(context, input) {
|
|
|
28610
28636
|
prompt: input.step.instructions ? `${input.step.instructions}
|
|
28611
28637
|
|
|
28612
28638
|
${generatedPrompt}` : generatedPrompt,
|
|
28613
|
-
thinking: input.stepAttempt <= 1 ? "low" : "medium",
|
|
28614
28639
|
permission: Object.values(input.step.repositories).some((access) => access === "write") ? "edit" : "read-only",
|
|
28615
28640
|
...(input.step.kind === "agent" || input.step.kind === "moa") && input.step.timeoutMs !== void 0 ? { timeoutMs: input.step.timeoutMs } : {},
|
|
28616
28641
|
contextPacket,
|
|
28617
|
-
...resolvedRoute ? {
|
|
28642
|
+
...resolvedRoute?.effort !== void 0 ? { thinking: resolvedRoute.effort } : {},
|
|
28643
|
+
...resolvedRoute ? { harness: resolvedRoute.harness, provider: resolvedRoute.provider, model: resolvedRoute.model } : {}
|
|
28618
28644
|
},
|
|
28619
28645
|
controller,
|
|
28620
28646
|
state: next
|
|
@@ -28759,13 +28785,14 @@ async function drivePanel(context, panel, producer) {
|
|
|
28759
28785
|
})();
|
|
28760
28786
|
pending.set(member.attemptId, work);
|
|
28761
28787
|
};
|
|
28788
|
+
let routeHandoff;
|
|
28762
28789
|
const tryBirth = () => {
|
|
28763
|
-
if (stopBirths) return void 0;
|
|
28790
|
+
if (stopBirths || routeHandoff) return void 0;
|
|
28764
28791
|
return context.eventStore.transaction(() => {
|
|
28765
28792
|
const run = requireRun(context, runId);
|
|
28766
28793
|
const state = foldStoredKxmRun(context, run);
|
|
28767
28794
|
if (!birthAllowed(state, panel.step)) return void 0;
|
|
28768
|
-
|
|
28795
|
+
const born = birthMember(context, {
|
|
28769
28796
|
run,
|
|
28770
28797
|
plan: panel.plan,
|
|
28771
28798
|
step: panel.step,
|
|
@@ -28774,6 +28801,11 @@ async function drivePanel(context, panel, producer) {
|
|
|
28774
28801
|
producerId: producer.id,
|
|
28775
28802
|
dispatchSources: panel.dispatchSources
|
|
28776
28803
|
});
|
|
28804
|
+
if ("handoff" in born) {
|
|
28805
|
+
routeHandoff = born.handoff;
|
|
28806
|
+
return void 0;
|
|
28807
|
+
}
|
|
28808
|
+
return born;
|
|
28777
28809
|
});
|
|
28778
28810
|
};
|
|
28779
28811
|
const settleInvoked = (member, produced) => {
|
|
@@ -28817,6 +28849,10 @@ async function drivePanel(context, panel, producer) {
|
|
|
28817
28849
|
while (!stopBirths && !settlementFailed) {
|
|
28818
28850
|
try {
|
|
28819
28851
|
const next = tryBirth();
|
|
28852
|
+
if (routeHandoff) {
|
|
28853
|
+
stopBirths = true;
|
|
28854
|
+
break;
|
|
28855
|
+
}
|
|
28820
28856
|
if (!next) break;
|
|
28821
28857
|
launch(next);
|
|
28822
28858
|
} catch {
|
|
@@ -28827,6 +28863,13 @@ async function drivePanel(context, panel, producer) {
|
|
|
28827
28863
|
return unreconciledHandoff(state, panel.stepId);
|
|
28828
28864
|
}
|
|
28829
28865
|
}
|
|
28866
|
+
if (routeHandoff) {
|
|
28867
|
+
const handoff = routeHandoff;
|
|
28868
|
+
abortOwned();
|
|
28869
|
+
await drainPendingInvoked();
|
|
28870
|
+
const state = foldStoredKxmRun(context, requireRun(context, runId));
|
|
28871
|
+
return { state, handoff };
|
|
28872
|
+
}
|
|
28830
28873
|
if (pending.size === 0) break;
|
|
28831
28874
|
const finished = await Promise.race(pending.values());
|
|
28832
28875
|
pending.delete(finished.attemptId);
|
|
@@ -29390,25 +29433,7 @@ function unsupportedStep(plan, step, producerId) {
|
|
|
29390
29433
|
}
|
|
29391
29434
|
return void 0;
|
|
29392
29435
|
}
|
|
29393
|
-
function
|
|
29394
|
-
if (!existsSync12(path)) return void 0;
|
|
29395
|
-
try {
|
|
29396
|
-
const parsed = (0, import_yaml9.parse)(readFileSync10(path, "utf8"));
|
|
29397
|
-
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) return parsed;
|
|
29398
|
-
} catch {
|
|
29399
|
-
return void 0;
|
|
29400
|
-
}
|
|
29401
|
-
return void 0;
|
|
29402
|
-
}
|
|
29403
|
-
function agentHarness(projectRoot, agentId) {
|
|
29404
|
-
const harness = readYamlRecord(join15(projectRoot, ".kxm", "agents", `${agentId}.yaml`))?.harness;
|
|
29405
|
-
return typeof harness === "string" && harness.length > 0 ? harness : void 0;
|
|
29406
|
-
}
|
|
29407
|
-
function projectDefaultHarness(projectRoot) {
|
|
29408
|
-
const harness = readYamlRecord(join15(projectRoot, ".kxm", "project.yaml"))?.defaultHarness;
|
|
29409
|
-
return typeof harness === "string" && harness.length > 0 ? harness : "pi";
|
|
29410
|
-
}
|
|
29411
|
-
function unsupportedLiveWrite(projectRoot, step, agentId, selector, maxConcurrentRuns) {
|
|
29436
|
+
function unsupportedLiveWrite(projectRoot, step, route, maxConcurrentRuns) {
|
|
29412
29437
|
if (!Object.values(step.repositories).some((access) => access === "write")) return void 0;
|
|
29413
29438
|
if (step.assignments.maximum !== 1) {
|
|
29414
29439
|
return {
|
|
@@ -29424,42 +29449,23 @@ function unsupportedLiveWrite(projectRoot, step, agentId, selector, maxConcurren
|
|
|
29424
29449
|
detail: "live write steps require limits.maxConcurrentRuns of 1; concurrent runs share one checkout"
|
|
29425
29450
|
};
|
|
29426
29451
|
}
|
|
29427
|
-
|
|
29428
|
-
if (!oneShotWriterArgs(harness)) {
|
|
29452
|
+
if (!oneShotWriterArgs(route.harness)) {
|
|
29429
29453
|
return {
|
|
29430
29454
|
reason: "step_unsupported",
|
|
29431
29455
|
field: "repositories",
|
|
29432
|
-
detail: `live write steps require an audited writer profile; ${harness} has none`
|
|
29456
|
+
detail: `live write steps require an audited writer profile; ${route.harness} has none`
|
|
29433
29457
|
};
|
|
29434
29458
|
}
|
|
29435
|
-
const
|
|
29436
|
-
if (!
|
|
29437
|
-
|
|
29438
|
-
|
|
29439
|
-
|
|
29440
|
-
|
|
29441
|
-
const routes = roster.routes;
|
|
29442
|
-
const lineup = roster.lineup;
|
|
29443
|
-
const writerIds = lineup && typeof lineup === "object" && !Array.isArray(lineup) ? lineup.writer : void 0;
|
|
29444
|
-
if (!routes || typeof routes !== "object" || Array.isArray(routes) || !Array.isArray(writerIds)) {
|
|
29445
|
-
return { reason: "step_unsupported", field: "model", detail: "developer roster has no writer lineup" };
|
|
29446
|
-
}
|
|
29447
|
-
const allowed = writerIds.some((id) => {
|
|
29448
|
-
if (typeof id !== "string") return false;
|
|
29449
|
-
const route = routes[id];
|
|
29450
|
-
if (!route || typeof route !== "object" || Array.isArray(route)) return false;
|
|
29451
|
-
const record2 = route;
|
|
29452
|
-
if (record2.harness !== harness || record2.status !== "admitted") return false;
|
|
29453
|
-
if (!Array.isArray(record2.permissions) || !record2.permissions.includes("edit")) return false;
|
|
29454
|
-
const model = typeof record2.model === "string" ? record2.model : "";
|
|
29455
|
-
const vendor = typeof record2.vendor === "string" ? record2.vendor : "";
|
|
29456
|
-
return model === selector || vendor.length > 0 && `${vendor}/${model}` === selector;
|
|
29457
|
-
});
|
|
29458
|
-
if (!allowed) {
|
|
29459
|
+
const writerIds = listRoleBindings(projectRoot).writer;
|
|
29460
|
+
if (!Array.isArray(writerIds) || writerIds.length === 0) {
|
|
29461
|
+
return { reason: "step_unsupported", field: "model", detail: "writer roster has no admitted edit route" };
|
|
29462
|
+
}
|
|
29463
|
+
const named = writerIds.includes(route.routeId);
|
|
29464
|
+
if (!named || !route.permissions.includes("edit")) {
|
|
29459
29465
|
return {
|
|
29460
29466
|
reason: "step_unsupported",
|
|
29461
29467
|
field: "model",
|
|
29462
|
-
detail: `live write route ${selector} on ${harness} is not on the
|
|
29468
|
+
detail: `live write route ${route.selector} on ${route.harness} is not an admitted edit route on the writer roster`
|
|
29463
29469
|
};
|
|
29464
29470
|
}
|
|
29465
29471
|
return void 0;
|
|
@@ -29896,20 +29902,11 @@ function determineOutcome(text, allowedOutcomes) {
|
|
|
29896
29902
|
return "failed";
|
|
29897
29903
|
}
|
|
29898
29904
|
function createKxmOneShotProducer(options = {}) {
|
|
29899
|
-
const defaultHarness = options.defaultHarness ?? "claude";
|
|
29900
29905
|
const running = /* @__PURE__ */ new Map();
|
|
29901
29906
|
let closed = false;
|
|
29902
|
-
function
|
|
29907
|
+
function requireHarness(request) {
|
|
29903
29908
|
if (request.harness) return request.harness;
|
|
29904
|
-
|
|
29905
|
-
const resolved = options.resolveHarness(request.agentId, request.runId);
|
|
29906
|
-
if (resolved) return resolved;
|
|
29907
|
-
}
|
|
29908
|
-
if (options.resolveModel) {
|
|
29909
|
-
const resolved = options.resolveModel(request.agentId, request.runId);
|
|
29910
|
-
if (resolved?.harness) return resolved.harness;
|
|
29911
|
-
}
|
|
29912
|
-
return defaultHarness;
|
|
29909
|
+
throw new Error("producer_harness_required");
|
|
29913
29910
|
}
|
|
29914
29911
|
function parseModelString(spec, harness) {
|
|
29915
29912
|
const trimmed = spec.trim();
|
|
@@ -29971,7 +29968,7 @@ function createKxmOneShotProducer(options = {}) {
|
|
|
29971
29968
|
}
|
|
29972
29969
|
async function executeRequest(request) {
|
|
29973
29970
|
const startTime = Date.now();
|
|
29974
|
-
const harness =
|
|
29971
|
+
const harness = requireHarness(request);
|
|
29975
29972
|
const resolved = resolveModelForRequest(request, harness);
|
|
29976
29973
|
if (closed) throw new Error("oneshot_producer_closed");
|
|
29977
29974
|
const cancelled = () => ({
|
|
@@ -31221,24 +31218,7 @@ async function startKxmRuntimeSupervisorInner(paths, requestedPortOption, now, e
|
|
|
31221
31218
|
const delayMs = typeof body.delayMs === "number" && body.delayMs > 0 ? body.delayMs : 0;
|
|
31222
31219
|
const createProducer = () => body.mode === "live" ? createKxmOneShotProducer({
|
|
31223
31220
|
projectRoot,
|
|
31224
|
-
timeoutMs: kxmProjectAdmissionLimits(bundle).agentStepTimeoutMs
|
|
31225
|
-
defaultHarness: String(bundle.project.value.defaultHarness ?? "pi"),
|
|
31226
|
-
resolveHarness: (agentId) => {
|
|
31227
|
-
const agent = bundle.agents.get(agentId);
|
|
31228
|
-
return typeof agent?.value.harness === "string" ? agent.value.harness : void 0;
|
|
31229
|
-
},
|
|
31230
|
-
resolveModel: (agentId) => {
|
|
31231
|
-
const agent = bundle.agents.get(agentId);
|
|
31232
|
-
const model = agent?.value.model;
|
|
31233
|
-
if (!model || typeof model !== "object" || Array.isArray(model)) return void 0;
|
|
31234
|
-
const value = model;
|
|
31235
|
-
const provider = typeof value.provider === "string" ? value.provider : void 0;
|
|
31236
|
-
const modelName = typeof value.model === "string" ? value.model : void 0;
|
|
31237
|
-
if (!provider || !modelName || !isRouteAdmitted(projectRoot, `${provider}/${modelName}`)) {
|
|
31238
|
-
throw new Error("producer_route_not_admitted");
|
|
31239
|
-
}
|
|
31240
|
-
return { provider, model: modelName };
|
|
31241
|
-
}
|
|
31221
|
+
timeoutMs: kxmProjectAdmissionLimits(bundle).agentStepTimeoutMs
|
|
31242
31222
|
}) : createKxmSimulatedProducer(async () => {
|
|
31243
31223
|
if (delayMs > 0) {
|
|
31244
31224
|
await new Promise((r) => setTimeout(r, delayMs));
|