@lsctech/polaris 0.4.9 → 0.5.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.
@@ -195,6 +195,10 @@ function compileStartupPacket(input) {
195
195
  prompt_mode: 'full',
196
196
  prompt_metrics: { mode: 'full', char_count: 0, estimated_tokens: 0 },
197
197
  role_context: roleContextForWorkerRole('startup'),
198
+ routing_context: {
199
+ task_type: "startup",
200
+ required_capabilities: ["orchestration"],
201
+ },
198
202
  result_file_contract: {
199
203
  result_file: input.resultFile,
200
204
  result_required_fields: Object.fromEntries([
@@ -287,6 +291,10 @@ function compileImplPacket(input) {
287
291
  prompt_mode: promptMode,
288
292
  prompt_metrics: promptResult.metrics,
289
293
  role_context: roleContextForWorkerRole('impl'),
294
+ routing_context: {
295
+ task_type: "impl",
296
+ required_capabilities: ["implementation"],
297
+ },
290
298
  prohibited_write_paths: exports.WORKER_PROHIBITED_WRITE_PATHS,
291
299
  result_file_contract: {
292
300
  result_file: input.resultFile,
@@ -341,6 +349,10 @@ function compileFinalizePacket(input) {
341
349
  prompt_mode: 'full',
342
350
  prompt_metrics: { mode: 'full', char_count: 0, estimated_tokens: 0 },
343
351
  role_context: roleContextForWorkerRole('finalize'),
352
+ routing_context: {
353
+ task_type: "finalize",
354
+ required_capabilities: ["finalization"],
355
+ },
344
356
  result_file_contract: {
345
357
  result_file: input.resultFile,
346
358
  result_required_fields: Object.fromEntries([
@@ -390,6 +402,10 @@ function compilePreflightPacket(input) {
390
402
  prompt_mode: 'full',
391
403
  prompt_metrics: { mode: 'full', char_count: 0, estimated_tokens: 0 },
392
404
  role_context: roleContextForWorkerRole('preflight'),
405
+ routing_context: {
406
+ task_type: "startup",
407
+ required_capabilities: ["orchestration"],
408
+ },
393
409
  result_file_contract: {
394
410
  result_file: input.resultFile,
395
411
  result_required_fields: Object.fromEntries([
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.selectNextChild = selectNextChild;
4
+ exports.selectChildSlotClaims = selectChildSlotClaims;
4
5
  /**
5
6
  * Select the next child to execute.
6
7
  *
@@ -14,3 +15,83 @@ function selectNextChild(state) {
14
15
  return null;
15
16
  return [...state.open_children].sort()[0] ?? null;
16
17
  }
18
+ function countActiveSlotsByProvider(claims) {
19
+ const activeSlotsByProvider = {};
20
+ for (const claim of claims) {
21
+ if (!claim.provider)
22
+ continue;
23
+ activeSlotsByProvider[claim.provider] = (activeSlotsByProvider[claim.provider] ?? 0) + 1;
24
+ }
25
+ return activeSlotsByProvider;
26
+ }
27
+ function selectChildSlotClaims(args) {
28
+ const now = args.now ?? new Date();
29
+ const nowMs = now.getTime();
30
+ const openSet = new Set(args.open_children);
31
+ const completedSet = new Set(args.completed_children);
32
+ const expired_claims = [];
33
+ const retainedClaims = args.existing_claims.filter((claim) => {
34
+ const expiresAt = new Date(claim.expires_at).getTime();
35
+ const notExpired = Number.isFinite(expiresAt) && expiresAt > nowMs;
36
+ const stillOpen = openSet.has(claim.child_id);
37
+ if (!notExpired || !stillOpen) {
38
+ expired_claims.push(claim.child_id);
39
+ return false;
40
+ }
41
+ return true;
42
+ });
43
+ const rejected_children = {};
44
+ const claimedChildren = new Set(retainedClaims.map((claim) => claim.child_id));
45
+ const availableSlots = Math.max(0, args.max_concurrent - retainedClaims.length);
46
+ const newClaims = [];
47
+ if (availableSlots > 0) {
48
+ for (const childId of args.open_children) {
49
+ if (newClaims.length >= availableSlots)
50
+ break;
51
+ if (childId === args.active_child)
52
+ continue;
53
+ if (claimedChildren.has(childId))
54
+ continue;
55
+ const dependencies = args.get_dependencies(childId);
56
+ const unmetDependencies = dependencies.filter((dependency) => openSet.has(dependency) && !completedSet.has(dependency));
57
+ if (unmetDependencies.length > 0) {
58
+ rejected_children[childId] = "blocked-dependency";
59
+ continue;
60
+ }
61
+ const decision = args.decide_route({
62
+ childId,
63
+ activeSlotsByProvider: countActiveSlotsByProvider([...retainedClaims, ...newClaims]),
64
+ });
65
+ const hardIneligibleReasons = new Set([
66
+ "role-disabled",
67
+ "not-in-policy",
68
+ "quota-exhausted",
69
+ "trust-too-low",
70
+ "capability-mismatch",
71
+ "cost-policy",
72
+ "no-slot",
73
+ ]);
74
+ const routingExhausted = decision.exhaustedReason !== undefined &&
75
+ (hardIneligibleReasons.has(decision.exhaustedReason) || decision.mode !== "delegated");
76
+ const canClaim = decision.selectedProvider !== undefined || decision.mode === "delegated";
77
+ if (routingExhausted || !canClaim) {
78
+ rejected_children[childId] = "router-ineligible";
79
+ continue;
80
+ }
81
+ newClaims.push({
82
+ child_id: childId,
83
+ provider: decision.selectedProvider ?? null,
84
+ claimed_at: now.toISOString(),
85
+ expires_at: new Date(nowMs + args.claim_ttl_ms).toISOString(),
86
+ selection_reason: decision.selectionReason,
87
+ });
88
+ }
89
+ }
90
+ const slot_claims = [...retainedClaims, ...newClaims];
91
+ return {
92
+ selected_child: slot_claims[0]?.child_id ?? null,
93
+ slot_claims,
94
+ rejected_children,
95
+ expired_claims,
96
+ };
97
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lsctech/polaris",
3
- "version": "0.4.9",
3
+ "version": "0.5.0",
4
4
  "description": "Polaris — standalone taskchain orchestration framework for governed AI agent workflows",
5
5
  "bin": {
6
6
  "polaris": "dist/cli/index.js",