@kognai/orchestrator-core 0.2.2 → 0.2.4

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.
@@ -136,6 +136,27 @@ export declare function spawnCitizen(req: SpawnRequest, opts?: {
136
136
  decision: SpawnDecision;
137
137
  citizen?: CitizenRecord;
138
138
  };
139
+ /**
140
+ * TICKET-334e — backfill an initial ACP for every citizen in the registry that
141
+ * has no entry in acp/trust-scores.json yet. These are pre-SAF citizens that were
142
+ * born scoreless (minted via bare mintCitizen before the canonical issuer seeded
143
+ * ACP at birth — see TICKET-334b). The router PASS-THROUGHs unscored agents, so
144
+ * this gives them a real routing profile instead of an implicit bypass.
145
+ *
146
+ * Classification reuses the SAF path (classifyRequest → initialAcp) keyed on the
147
+ * citizen's owner lineage + agent_name, so a backfilled score is identical to the
148
+ * one the same agent would receive if spawned today. Idempotent: writeInitialAcp
149
+ * skips any agent_name that already has a score, so re-running only fills gaps.
150
+ */
151
+ export declare function backfillAcpForRegistry(): {
152
+ scanned: number;
153
+ seeded: {
154
+ agent_name: string;
155
+ classification: SpawnClass;
156
+ score: number;
157
+ }[];
158
+ skipped: number;
159
+ };
139
160
  /**
140
161
  * Emergency bypass — Founder only. Overrides all gates including health and
141
162
  * constitutional conditional findings. Logs prominently to KSL.
@@ -24,6 +24,7 @@ exports.issueSpawnDecision = issueSpawnDecision;
24
24
  exports.sovereignSpawn = sovereignSpawn;
25
25
  exports.deriveOwner = deriveOwner;
26
26
  exports.spawnCitizen = spawnCitizen;
27
+ exports.backfillAcpForRegistry = backfillAcpForRegistry;
27
28
  exports.founderEmergencySpawn = founderEmergencySpawn;
28
29
  exports.getSpawnRegistry = getSpawnRegistry;
29
30
  exports.batchSpawn = batchSpawn;
@@ -353,6 +354,68 @@ function spawnCitizen(req, opts = {}) {
353
354
  writeInitialAcp(citizen.agent_name, decision.initial_acp_score);
354
355
  return { decision, citizen };
355
356
  }
357
+ /**
358
+ * TICKET-334e — derive the constitutional requester DID for an EXISTING citizen
359
+ * from its owner lineage, so classifyRequest() sorts it the same way a fresh
360
+ * spawn from that owner would (external → EXTERNAL sub-floor; everything else by
361
+ * role). Mirrors the DID shapes deriveOwner() reads.
362
+ */
363
+ function requesterDidForCitizen(c) {
364
+ const id = c.owner_id || c.company || 'kognai';
365
+ switch (c.owner_kind) {
366
+ case 'external': return `did:external:${id}:${c.agent_name}`;
367
+ case 'user': return `did:kognai:citizen:${id}`;
368
+ case 'scs': return `did:kognai:scs:${id}:${c.agent_name}`;
369
+ default: return `did:kognai:${id}`; // company / legacy
370
+ }
371
+ }
372
+ /** Read the agent_name keys already present in acp/trust-scores.json. */
373
+ function readAcpScoreKeys() {
374
+ try {
375
+ const { readFileSync } = require('fs');
376
+ const { join } = require('path');
377
+ const acpPath = join((0, engine_paths_1.resolveEnginePaths)().root, 'acp', 'trust-scores.json');
378
+ const data = JSON.parse(readFileSync(acpPath, 'utf-8'));
379
+ return new Set(Object.keys(data?.scores ?? {}));
380
+ }
381
+ catch {
382
+ return new Set();
383
+ }
384
+ }
385
+ /**
386
+ * TICKET-334e — backfill an initial ACP for every citizen in the registry that
387
+ * has no entry in acp/trust-scores.json yet. These are pre-SAF citizens that were
388
+ * born scoreless (minted via bare mintCitizen before the canonical issuer seeded
389
+ * ACP at birth — see TICKET-334b). The router PASS-THROUGHs unscored agents, so
390
+ * this gives them a real routing profile instead of an implicit bypass.
391
+ *
392
+ * Classification reuses the SAF path (classifyRequest → initialAcp) keyed on the
393
+ * citizen's owner lineage + agent_name, so a backfilled score is identical to the
394
+ * one the same agent would receive if spawned today. Idempotent: writeInitialAcp
395
+ * skips any agent_name that already has a score, so re-running only fills gaps.
396
+ */
397
+ function backfillAcpForRegistry() {
398
+ const reg = (0, citizenship_1.readRegistry)();
399
+ const alreadyScored = readAcpScoreKeys();
400
+ const seeded = [];
401
+ let skipped = 0;
402
+ for (const c of reg.citizens) {
403
+ if (!c.agent_name || alreadyScored.has(c.agent_name)) {
404
+ skipped++;
405
+ continue;
406
+ }
407
+ const classification = classifyRequest({
408
+ requester_did: requesterDidForCitizen(c),
409
+ requested_role: c.agent_name,
410
+ requested_capabilities: [],
411
+ purpose: `TICKET-334e ACP backfill for pre-SAF citizen ${c.agent_name}`,
412
+ });
413
+ const score = initialAcp(classification);
414
+ writeInitialAcp(c.agent_name, score);
415
+ seeded.push({ agent_name: c.agent_name, classification, score });
416
+ }
417
+ return { scanned: reg.citizens.length, seeded, skipped };
418
+ }
356
419
  /**
357
420
  * Emergency bypass — Founder only. Overrides all gates including health and
358
421
  * constitutional conditional findings. Logs prominently to KSL.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kognai/orchestrator-core",
3
- "version": "0.2.2",
3
+ "version": "0.2.4",
4
4
  "description": "Kognai sovereign orchestrator — core engine (template-agnostic). Shared by all products (Kognai/coding, Voxight/market-intel, Invoica/fin-compliance); each supplies only its template. Replaces per-repo forks of orchestrate-agents-v2 / sprint-runner / lib.",
5
5
  "license": "MIT",
6
6
  "author": "SkinGem",