@kognai/orchestrator-core 0.1.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.
Files changed (144) hide show
  1. package/README.md +44 -0
  2. package/dist/index.d.ts +63 -0
  3. package/dist/index.js +175 -0
  4. package/dist/lib/aar-middleware.d.ts +6 -0
  5. package/dist/lib/aar-middleware.js +70 -0
  6. package/dist/lib/aar-types.d.ts +34 -0
  7. package/dist/lib/aar-types.js +4 -0
  8. package/dist/lib/acp-engine.d.ts +68 -0
  9. package/dist/lib/acp-engine.js +123 -0
  10. package/dist/lib/acp.d.ts +61 -0
  11. package/dist/lib/acp.js +425 -0
  12. package/dist/lib/agent-registry.d.ts +50 -0
  13. package/dist/lib/agent-registry.js +137 -0
  14. package/dist/lib/anthropic-direct.d.ts +27 -0
  15. package/dist/lib/anthropic-direct.js +109 -0
  16. package/dist/lib/asmr-extractor.d.ts +40 -0
  17. package/dist/lib/asmr-extractor.js +151 -0
  18. package/dist/lib/asmr-retrieval.d.ts +76 -0
  19. package/dist/lib/asmr-retrieval.js +311 -0
  20. package/dist/lib/asmr.d.ts +8 -0
  21. package/dist/lib/asmr.js +24 -0
  22. package/dist/lib/brainx-client.d.ts +72 -0
  23. package/dist/lib/brainx-client.js +200 -0
  24. package/dist/lib/brainx-embed.d.ts +14 -0
  25. package/dist/lib/brainx-embed.js +139 -0
  26. package/dist/lib/brainx-swarm-bridge.d.ts +93 -0
  27. package/dist/lib/brainx-swarm-bridge.js +242 -0
  28. package/dist/lib/byterover-client.d.ts +19 -0
  29. package/dist/lib/byterover-client.js +59 -0
  30. package/dist/lib/ceo-wallet.d.ts +37 -0
  31. package/dist/lib/ceo-wallet.js +176 -0
  32. package/dist/lib/chomsky-gate.d.ts +24 -0
  33. package/dist/lib/chomsky-gate.js +178 -0
  34. package/dist/lib/chomsky-runner.d.ts +29 -0
  35. package/dist/lib/chomsky-runner.js +157 -0
  36. package/dist/lib/citizen-score-contract.d.ts +72 -0
  37. package/dist/lib/citizen-score-contract.js +16 -0
  38. package/dist/lib/citizen-score-registry.d.ts +25 -0
  39. package/dist/lib/citizen-score-registry.js +65 -0
  40. package/dist/lib/citizenship.d.ts +103 -0
  41. package/dist/lib/citizenship.js +272 -0
  42. package/dist/lib/clawrouter-client.d.ts +37 -0
  43. package/dist/lib/clawrouter-client.js +148 -0
  44. package/dist/lib/code-asset-crystalliser.d.ts +41 -0
  45. package/dist/lib/code-asset-crystalliser.js +181 -0
  46. package/dist/lib/code-failure-logger.d.ts +27 -0
  47. package/dist/lib/code-failure-logger.js +42 -0
  48. package/dist/lib/cto-approval-gate.d.ts +45 -0
  49. package/dist/lib/cto-approval-gate.js +478 -0
  50. package/dist/lib/cto-gate-types.d.ts +28 -0
  51. package/dist/lib/cto-gate-types.js +8 -0
  52. package/dist/lib/decomposer-feedback.d.ts +54 -0
  53. package/dist/lib/decomposer-feedback.js +115 -0
  54. package/dist/lib/emotional-safety-gate.d.ts +48 -0
  55. package/dist/lib/emotional-safety-gate.js +97 -0
  56. package/dist/lib/engine-paths.d.ts +13 -0
  57. package/dist/lib/engine-paths.js +32 -0
  58. package/dist/lib/event-bus-listener.d.ts +8 -0
  59. package/dist/lib/event-bus-listener.js +144 -0
  60. package/dist/lib/event-bus-publisher.d.ts +25 -0
  61. package/dist/lib/event-bus-publisher.js +188 -0
  62. package/dist/lib/event-bus-types.d.ts +73 -0
  63. package/dist/lib/event-bus-types.js +23 -0
  64. package/dist/lib/failure-library.d.ts +178 -0
  65. package/dist/lib/failure-library.js +349 -0
  66. package/dist/lib/ksl/error-log.d.ts +28 -0
  67. package/dist/lib/ksl/error-log.js +43 -0
  68. package/dist/lib/ksl/index.d.ts +9 -0
  69. package/dist/lib/ksl/index.js +25 -0
  70. package/dist/lib/ksl/orchestrator-tap.d.ts +16 -0
  71. package/dist/lib/ksl/orchestrator-tap.js +85 -0
  72. package/dist/lib/ksl/record-writer.d.ts +46 -0
  73. package/dist/lib/ksl/record-writer.js +45 -0
  74. package/dist/lib/llm-cost-table.d.ts +36 -0
  75. package/dist/lib/llm-cost-table.js +90 -0
  76. package/dist/lib/local-model-router.d.ts +27 -0
  77. package/dist/lib/local-model-router.js +61 -0
  78. package/dist/lib/mc-client.d.ts +51 -0
  79. package/dist/lib/mc-client.js +249 -0
  80. package/dist/lib/model-router-contract.d.ts +91 -0
  81. package/dist/lib/model-router-contract.js +19 -0
  82. package/dist/lib/model-router-registry.d.ts +24 -0
  83. package/dist/lib/model-router-registry.js +52 -0
  84. package/dist/lib/model-router.d.ts +20 -0
  85. package/dist/lib/model-router.js +79 -0
  86. package/dist/lib/monotask-state-machine.d.ts +19 -0
  87. package/dist/lib/monotask-state-machine.js +131 -0
  88. package/dist/lib/neutral-prompt-checker.d.ts +22 -0
  89. package/dist/lib/neutral-prompt-checker.js +130 -0
  90. package/dist/lib/notion-direct.d.ts +92 -0
  91. package/dist/lib/notion-direct.js +381 -0
  92. package/dist/lib/ollama-client.d.ts +37 -0
  93. package/dist/lib/ollama-client.js +158 -0
  94. package/dist/lib/omel/credential-vault.d.ts +57 -0
  95. package/dist/lib/omel/credential-vault.js +324 -0
  96. package/dist/lib/omel/human-brake.d.ts +32 -0
  97. package/dist/lib/omel/human-brake.js +289 -0
  98. package/dist/lib/omel/index.d.ts +10 -0
  99. package/dist/lib/omel/index.js +26 -0
  100. package/dist/lib/omel/phantom-workspace.d.ts +31 -0
  101. package/dist/lib/omel/phantom-workspace.js +256 -0
  102. package/dist/lib/omel/wipe-witness.d.ts +75 -0
  103. package/dist/lib/omel/wipe-witness.js +398 -0
  104. package/dist/lib/orchestrate-engine.d.ts +25 -0
  105. package/dist/lib/orchestrate-engine.js +4436 -0
  106. package/dist/lib/perm-judge.d.ts +46 -0
  107. package/dist/lib/perm-judge.js +173 -0
  108. package/dist/lib/plumber/conformance.d.ts +54 -0
  109. package/dist/lib/plumber/conformance.js +121 -0
  110. package/dist/lib/plumber/index.d.ts +9 -0
  111. package/dist/lib/plumber/index.js +25 -0
  112. package/dist/lib/plumber/observer.d.ts +52 -0
  113. package/dist/lib/plumber/observer.js +180 -0
  114. package/dist/lib/plumber/types.d.ts +78 -0
  115. package/dist/lib/plumber/types.js +29 -0
  116. package/dist/lib/research-impl-gate.d.ts +16 -0
  117. package/dist/lib/research-impl-gate.js +105 -0
  118. package/dist/lib/sherlock-memory.d.ts +29 -0
  119. package/dist/lib/sherlock-memory.js +105 -0
  120. package/dist/lib/skill-crystalliser.d.ts +44 -0
  121. package/dist/lib/skill-crystalliser.js +60 -0
  122. package/dist/lib/sprint-runner-engine.d.ts +27 -0
  123. package/dist/lib/sprint-runner-engine.js +1042 -0
  124. package/dist/lib/sprint-state.d.ts +71 -0
  125. package/dist/lib/sprint-state.js +202 -0
  126. package/dist/lib/stuck-handler.d.ts +17 -0
  127. package/dist/lib/stuck-handler.js +249 -0
  128. package/dist/lib/task-contract-checker.d.ts +17 -0
  129. package/dist/lib/task-contract-checker.js +29 -0
  130. package/dist/lib/task-router/index.d.ts +17 -0
  131. package/dist/lib/task-router/index.js +52 -0
  132. package/dist/lib/task-router/router/generate-execution-id.d.ts +10 -0
  133. package/dist/lib/task-router/router/generate-execution-id.js +24 -0
  134. package/dist/lib/task-router/router/resolve-route.d.ts +2 -0
  135. package/dist/lib/task-router/router/resolve-route.js +49 -0
  136. package/dist/lib/task-router/types.d.ts +79 -0
  137. package/dist/lib/task-router/types.js +39 -0
  138. package/dist/lib/token-budget-validator.d.ts +44 -0
  139. package/dist/lib/token-budget-validator.js +84 -0
  140. package/dist/lib/trust-score-updater.d.ts +30 -0
  141. package/dist/lib/trust-score-updater.js +107 -0
  142. package/dist/lib/wallet-state.d.ts +26 -0
  143. package/dist/lib/wallet-state.js +85 -0
  144. package/package.json +27 -0
@@ -0,0 +1,78 @@
1
+ /**
2
+ * Plumber — data contracts (TICKET-216, observer half).
3
+ *
4
+ * The Plumber is the engine's self-healing OBSERVABILITY layer (Layer 4 Health /
5
+ * Layer 7 Plumber). This module defines the contracts for the READ-MOSTLY observer:
6
+ * it consumes KSL records, judges them against SOP/position conformance, and routes
7
+ * observations to sinks (failure substrate, skill-candidate queue, plumber.alert).
8
+ *
9
+ * IMPORTANT — the observer NEVER writes code. It only produces observations and
10
+ * writes to logs/queues/events. The autonomous fixer is a separate, gated ticket.
11
+ *
12
+ * Position-Map context (TICKET-153) is a first-class input: conformance is judged
13
+ * RELATIVE to the agent's Kognai-architectural position, and failures are weighted
14
+ * by the impacted wedge dimension (sovereignty / security / intelligence / memory).
15
+ *
16
+ * Zero-dep: stdlib + in-core KSL types only.
17
+ */
18
+ import type { KSLRecord } from '../ksl/record-writer';
19
+ export type SovereigntyTier = 1 | 2 | 3 | 4;
20
+ export type OptimizationProfile = 'security-first' | 'compliance-first' | 'performance-first' | 'sovereignty-first' | 'default' | (string & {});
21
+ /**
22
+ * What an agent knows about its place in Kognai when it does work. All fields are
23
+ * optional so the observer degrades gracefully when the map is absent (pre-AIAX-v0.2);
24
+ * cut over to the canonical AIAX v0.2 map schema when it lands.
25
+ */
26
+ export interface PositionMapContext {
27
+ layer?: string;
28
+ sovereigntyTier?: SovereigntyTier;
29
+ securityBlastRadius?: 'leaf' | 'moderate' | 'high';
30
+ intelligenceSink?: 'evidence' | 'simulation' | 'none';
31
+ memoryImpact?: 'low' | 'medium' | 'high';
32
+ role?: 'executor' | 'supervisor' | 'decomposer' | 'ceo' | 'cto' | 'reviewer' | (string & {});
33
+ optimizationProfile?: OptimizationProfile;
34
+ mandate?: {
35
+ costEnvelopeUsd?: number;
36
+ };
37
+ namespace?: 'production' | 'simulation';
38
+ }
39
+ export type ConformanceSeverity = 'info' | 'warn' | 'high';
40
+ /** The four wedge dimensions a failure can touch (for TICKET-152 weighting). */
41
+ export type PositionDimension = 'sovereignty' | 'security' | 'intelligence' | 'memory' | 'none';
42
+ export interface ConformanceResult {
43
+ checkId: string;
44
+ ok: boolean;
45
+ severity: ConformanceSeverity;
46
+ message: string;
47
+ dimension?: PositionDimension;
48
+ positionRelative?: boolean;
49
+ }
50
+ export type ObservationVerdict = 'conformant' | 'success_pattern' | 'failure' | 'anomaly';
51
+ export type PlumberFailureType = 'sop_nonconformance' | 'position_map_violation' | 'execution_error' | 'signal_mismatch';
52
+ export interface ObservationRef {
53
+ run_id: string;
54
+ sprint_id: string;
55
+ task_id: string;
56
+ attempt: number;
57
+ agent: string;
58
+ }
59
+ export interface PlumberObservation {
60
+ ref: ObservationRef;
61
+ verdict: ObservationVerdict;
62
+ conformance: ConformanceResult[];
63
+ failureType?: PlumberFailureType;
64
+ dimension?: PositionDimension;
65
+ severity: ConformanceSeverity;
66
+ signal_strength: 'low' | 'medium' | 'high';
67
+ summary: string;
68
+ observed_at: string;
69
+ }
70
+ export interface PlumberSinks {
71
+ /** A real failure (high-severity non-conformance, position-map violation, or execution error). */
72
+ onFailure(obs: PlumberObservation, record: KSLRecord, ctx?: PositionMapContext): void | Promise<void>;
73
+ /** A high-signal clean attempt worth crystallising into a skill. */
74
+ onSkillCandidate(obs: PlumberObservation, record: KSLRecord, ctx?: PositionMapContext): void | Promise<void>;
75
+ /** A warning-level anomaly worth a plumber.alert but not a failure. */
76
+ onAlert(obs: PlumberObservation, record: KSLRecord, ctx?: PositionMapContext): void | Promise<void>;
77
+ }
78
+ export declare function refOf(record: KSLRecord): ObservationRef;
@@ -0,0 +1,29 @@
1
+ "use strict";
2
+ /**
3
+ * Plumber — data contracts (TICKET-216, observer half).
4
+ *
5
+ * The Plumber is the engine's self-healing OBSERVABILITY layer (Layer 4 Health /
6
+ * Layer 7 Plumber). This module defines the contracts for the READ-MOSTLY observer:
7
+ * it consumes KSL records, judges them against SOP/position conformance, and routes
8
+ * observations to sinks (failure substrate, skill-candidate queue, plumber.alert).
9
+ *
10
+ * IMPORTANT — the observer NEVER writes code. It only produces observations and
11
+ * writes to logs/queues/events. The autonomous fixer is a separate, gated ticket.
12
+ *
13
+ * Position-Map context (TICKET-153) is a first-class input: conformance is judged
14
+ * RELATIVE to the agent's Kognai-architectural position, and failures are weighted
15
+ * by the impacted wedge dimension (sovereignty / security / intelligence / memory).
16
+ *
17
+ * Zero-dep: stdlib + in-core KSL types only.
18
+ */
19
+ Object.defineProperty(exports, "__esModule", { value: true });
20
+ exports.refOf = refOf;
21
+ function refOf(record) {
22
+ return {
23
+ run_id: record.run_id,
24
+ sprint_id: record.sprint_id,
25
+ task_id: record.task_id,
26
+ attempt: record.attempt,
27
+ agent: record.agent,
28
+ };
29
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * research-impl-gate.ts — Sprint TICKET-005-RULE2
3
+ * Rule 2 (Research/Implementation Separation): blocks implementation sprints
4
+ * from executing until their paired research sprint is marked done.
5
+ */
6
+ import type { SprintProposal } from './cto-gate-types';
7
+ export interface ResearchGateResult {
8
+ allowed: boolean;
9
+ reason: string;
10
+ }
11
+ /**
12
+ * Check whether an implementation sprint's research prerequisite is done.
13
+ * Returns allowed:true for non-implementation sprints or sprints without
14
+ * a research_sprint_id.
15
+ */
16
+ export declare function checkResearchGate(sprint: SprintProposal, projectRoot: string): ResearchGateResult;
@@ -0,0 +1,105 @@
1
+ "use strict";
2
+ /**
3
+ * research-impl-gate.ts — Sprint TICKET-005-RULE2
4
+ * Rule 2 (Research/Implementation Separation): blocks implementation sprints
5
+ * from executing until their paired research sprint is marked done.
6
+ */
7
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
8
+ if (k2 === undefined) k2 = k;
9
+ var desc = Object.getOwnPropertyDescriptor(m, k);
10
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
11
+ desc = { enumerable: true, get: function() { return m[k]; } };
12
+ }
13
+ Object.defineProperty(o, k2, desc);
14
+ }) : (function(o, m, k, k2) {
15
+ if (k2 === undefined) k2 = k;
16
+ o[k2] = m[k];
17
+ }));
18
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
19
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
20
+ }) : function(o, v) {
21
+ o["default"] = v;
22
+ });
23
+ var __importStar = (this && this.__importStar) || (function () {
24
+ var ownKeys = function(o) {
25
+ ownKeys = Object.getOwnPropertyNames || function (o) {
26
+ var ar = [];
27
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
28
+ return ar;
29
+ };
30
+ return ownKeys(o);
31
+ };
32
+ return function (mod) {
33
+ if (mod && mod.__esModule) return mod;
34
+ var result = {};
35
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
36
+ __setModuleDefault(result, mod);
37
+ return result;
38
+ };
39
+ })();
40
+ Object.defineProperty(exports, "__esModule", { value: true });
41
+ exports.checkResearchGate = checkResearchGate;
42
+ const fs = __importStar(require("fs"));
43
+ const path = __importStar(require("path"));
44
+ /**
45
+ * Check whether an implementation sprint's research prerequisite is done.
46
+ * Returns allowed:true for non-implementation sprints or sprints without
47
+ * a research_sprint_id.
48
+ */
49
+ function checkResearchGate(sprint, projectRoot) {
50
+ if (sprint.phase !== 'implementation') {
51
+ return { allowed: true, reason: 'Not an implementation sprint — no gate required.' };
52
+ }
53
+ if (!sprint.research_sprint_id) {
54
+ return { allowed: true, reason: 'Implementation sprint has no research_sprint_id — gate skipped.' };
55
+ }
56
+ const researchId = sprint.research_sprint_id;
57
+ // Check sprint-queue.json first (authoritative status)
58
+ // Try both the raw ID and without the 'sprint-' prefix
59
+ const queueIds = [researchId, researchId.replace(/^sprint-/, '')];
60
+ const queueFile = path.join(projectRoot, 'workspace', 'sprint-queue.json');
61
+ if (fs.existsSync(queueFile)) {
62
+ try {
63
+ const q = JSON.parse(fs.readFileSync(queueFile, 'utf-8'));
64
+ const items = q.queue || q;
65
+ const match = items.find((i) => queueIds.includes(i.sprint_id || i.sprint || i.id || ''));
66
+ if (match) {
67
+ if (match.status === 'done') {
68
+ return { allowed: true, reason: `Research sprint ${researchId} is done (queue).` };
69
+ }
70
+ return {
71
+ allowed: false,
72
+ reason: `Research sprint ${researchId} not done in queue (status: ${match.status || 'unknown'}).`,
73
+ };
74
+ }
75
+ }
76
+ catch { /* fall through */ }
77
+ }
78
+ // Fall back to workspace/sprints/{id}.json
79
+ const sprintFile = path.join(projectRoot, 'workspace', 'sprints', `${researchId}.json`);
80
+ if (fs.existsSync(sprintFile)) {
81
+ try {
82
+ const data = JSON.parse(fs.readFileSync(sprintFile, 'utf-8'));
83
+ if (data.status === 'done') {
84
+ return { allowed: true, reason: `Research sprint ${researchId} is done.` };
85
+ }
86
+ if (data.status) {
87
+ return {
88
+ allowed: false,
89
+ reason: `Research sprint ${researchId} not done (status: ${data.status}).`,
90
+ };
91
+ }
92
+ // File exists but has no status — treat as not done
93
+ return {
94
+ allowed: false,
95
+ reason: `Research sprint ${researchId} has no status field — treating as not done.`,
96
+ };
97
+ }
98
+ catch { /* fall through */ }
99
+ }
100
+ // Research sprint not found anywhere — block by default
101
+ return {
102
+ allowed: false,
103
+ reason: `Research sprint ${researchId} not found in sprints/ or sprint-queue.json.`,
104
+ };
105
+ }
@@ -0,0 +1,29 @@
1
+ /**
2
+ * sherlock-memory.ts — Sherlock v2 ASMR Memory Context (AMD-21-03)
3
+ *
4
+ * Wraps retrieveRelevantMemories() from asmr-retrieval.ts and formats
5
+ * the top-N relevant episodic entries into a markdown context block
6
+ * for injection into the Sherlock (supervisor) agent's review prompt.
7
+ *
8
+ * Replaces full MEMORY.md polling with query-driven six-vector retrieval.
9
+ * Routing: nomic-embed-text LOCAL — zero cloud cost (asmr-retrieval.ts).
10
+ * Fail-open: any error returns '' — never blocks the supervisor pipeline.
11
+ *
12
+ * FP-007: < 200 lines
13
+ */
14
+ /**
15
+ * Retrieve and format relevant episodic memory context for a Sherlock review.
16
+ *
17
+ * Uses the ASMR six-vector retrieval engine (nomic-embed-text local embeddings,
18
+ * cosine similarity ranking) to find the most semantically relevant prior sprint
19
+ * outcomes for the given task query.
20
+ *
21
+ * Returns a formatted markdown block ready for injection into the supervisor
22
+ * review prompt, or an empty string if retrieval yields nothing or fails.
23
+ *
24
+ * Fail-open: errors are silently absorbed — never blocks a review pipeline.
25
+ *
26
+ * @param query Task context string or task ID to drive retrieval
27
+ * @returns Formatted markdown memory block, or '' if unavailable
28
+ */
29
+ export declare function getSherlockMemoryContext(query: string): Promise<string>;
@@ -0,0 +1,105 @@
1
+ "use strict";
2
+ /**
3
+ * sherlock-memory.ts — Sherlock v2 ASMR Memory Context (AMD-21-03)
4
+ *
5
+ * Wraps retrieveRelevantMemories() from asmr-retrieval.ts and formats
6
+ * the top-N relevant episodic entries into a markdown context block
7
+ * for injection into the Sherlock (supervisor) agent's review prompt.
8
+ *
9
+ * Replaces full MEMORY.md polling with query-driven six-vector retrieval.
10
+ * Routing: nomic-embed-text LOCAL — zero cloud cost (asmr-retrieval.ts).
11
+ * Fail-open: any error returns '' — never blocks the supervisor pipeline.
12
+ *
13
+ * FP-007: < 200 lines
14
+ */
15
+ Object.defineProperty(exports, "__esModule", { value: true });
16
+ exports.getSherlockMemoryContext = getSherlockMemoryContext;
17
+ const asmr_retrieval_1 = require("./asmr-retrieval");
18
+ // AMD-21 P3 (Sprint 1537): three-tier retrieval pipeline. Default ON; set to
19
+ // '0' to fall back to the legacy single-tier nomic-embed retrieval.
20
+ const USE_THREE_TIER = process.env['SHERLOCK_USE_THREE_TIER'] !== '0';
21
+ const SHERLOCK_AGENT_ID = 'sherlock';
22
+ // ── Config ────────────────────────────────────────────────────────────────────
23
+ /** Number of top-ranked ASMR entries to inject into the supervisor context */
24
+ const MEMORY_LIMIT = 5;
25
+ /** Minimum character length for a query to be worth retrieving against */
26
+ const MIN_QUERY_LEN = 10;
27
+ /** Maximum characters of actionSummary to show per entry */
28
+ const SUMMARY_MAX_CHARS = 120;
29
+ // ── Formatters ────────────────────────────────────────────────────────────────
30
+ /**
31
+ * Format a single ASMR entry as a compact markdown row.
32
+ * Shows: rank, sprint/agent attribution, topic, intent, stance, summary.
33
+ */
34
+ function formatEntry(entry, rank) {
35
+ const { topic, intent, stance, emotion } = entry.vectors;
36
+ const agent = entry.agentId || 'unknown';
37
+ const sprint = entry.sprintId || '?';
38
+ const summary = (entry.actionSummary || '').substring(0, SUMMARY_MAX_CHARS);
39
+ const emotionTag = emotion ? ` [${emotion}]` : '';
40
+ return (`${rank}. **[${sprint} / ${agent}]**${emotionTag}\n` +
41
+ ` Topic: ${topic} — Intent: ${intent} (${stance})\n` +
42
+ ` ${summary}`);
43
+ }
44
+ /**
45
+ * Wrap the ranked entries in a labelled markdown context block.
46
+ * Returns empty string if no entries are available.
47
+ */
48
+ function formatMemoryBlock(entries) {
49
+ if (entries.length === 0)
50
+ return '';
51
+ const rows = entries.map((e, i) => formatEntry(e, i + 1));
52
+ return ('\n\n## Relevant Episodic Memory (Sherlock v2 / ASMR)\n' +
53
+ '_Top prior outcomes ranked by semantic similarity — use as pattern context only._\n\n' +
54
+ rows.join('\n\n'));
55
+ }
56
+ // ── Public API ────────────────────────────────────────────────────────────────
57
+ /**
58
+ * Retrieve and format relevant episodic memory context for a Sherlock review.
59
+ *
60
+ * Uses the ASMR six-vector retrieval engine (nomic-embed-text local embeddings,
61
+ * cosine similarity ranking) to find the most semantically relevant prior sprint
62
+ * outcomes for the given task query.
63
+ *
64
+ * Returns a formatted markdown block ready for injection into the supervisor
65
+ * review prompt, or an empty string if retrieval yields nothing or fails.
66
+ *
67
+ * Fail-open: errors are silently absorbed — never blocks a review pipeline.
68
+ *
69
+ * @param query Task context string or task ID to drive retrieval
70
+ * @returns Formatted markdown memory block, or '' if unavailable
71
+ */
72
+ async function getSherlockMemoryContext(query) {
73
+ if (!query || query.trim().length < MIN_QUERY_LEN)
74
+ return '';
75
+ try {
76
+ if (USE_THREE_TIER) {
77
+ const r = await (0, asmr_retrieval_1.retrieveThreeTier)(query, SHERLOCK_AGENT_ID, { maxResults: MEMORY_LIMIT });
78
+ // Log the per-tier breakdown so we can observe behaviour after rollout.
79
+ // stderr to stay out of stdout-piped consumers.
80
+ process.stderr.write(`[sherlock-memory] three-tier hits — hot=${r.hot.length} warm=${r.warm.length} ` +
81
+ `cold=${r.cold.length} merged=${r.merged.length} ` +
82
+ `lat(ms)=${r.latency_ms.total} (h=${r.latency_ms.hot} w=${r.latency_ms.warm} c=${r.latency_ms.cold})\n`);
83
+ return formatThreeTierBlock(r.merged);
84
+ }
85
+ const entries = await (0, asmr_retrieval_1.retrieveRelevantMemories)(query, MEMORY_LIMIT);
86
+ return formatMemoryBlock(entries);
87
+ }
88
+ catch {
89
+ // Non-blocking — ASMR retrieval failure must never stop a supervisor review
90
+ return '';
91
+ }
92
+ }
93
+ /** Render three-tier MemoryHit list using the existing markdown shape. */
94
+ function formatThreeTierBlock(merged) {
95
+ if (merged.length === 0)
96
+ return '';
97
+ const rows = merged.map((h, i) => {
98
+ const summary = h.content.substring(0, SUMMARY_MAX_CHARS);
99
+ const tier = h.source.toUpperCase();
100
+ return `${i + 1}. **[${tier}]** _(score ${h.score.toFixed(2)})_\n ${summary}`;
101
+ });
102
+ return ('\n\n## Relevant Episodic Memory (Sherlock v2 / ASMR three-tier)\n' +
103
+ '_Hot in-memory turns + warm BrainX vectors + cold archive scan, ranked by score._\n\n' +
104
+ rows.join('\n\n'));
105
+ }
@@ -0,0 +1,44 @@
1
+ export interface SkillScoreEntry {
2
+ sprint_id: string;
3
+ task_id: string;
4
+ score: number;
5
+ reviewed_at: string;
6
+ }
7
+ export interface SkillRecord {
8
+ skill_id: string;
9
+ type: 'kognai-owned' | 'user-uploaded';
10
+ name: string;
11
+ description: string;
12
+ definition: {
13
+ approach: string;
14
+ key_patterns: string[];
15
+ anti_patterns: string[];
16
+ };
17
+ optimal_settings: {
18
+ model: string;
19
+ task_target: 'local' | 'cloud-code';
20
+ max_attempts: number;
21
+ };
22
+ score_history: SkillScoreEntry[];
23
+ execution_count: number;
24
+ access_tier: 'internal' | 'free' | 'rental' | 'sale';
25
+ source_sprint: string;
26
+ source_task: string;
27
+ agent_id: string;
28
+ created_at: string;
29
+ updated_at: string;
30
+ }
31
+ export interface CrystalliseParams {
32
+ agentId: string;
33
+ taskId: string;
34
+ sprintId: string;
35
+ taskTitle: string;
36
+ taskType: string;
37
+ model: string;
38
+ taskTarget: 'local' | 'cloud-code';
39
+ score: number;
40
+ approachSummary: string;
41
+ keyPatterns: string[];
42
+ antiPatterns: string[];
43
+ }
44
+ export declare function crystalliseSkill(params: CrystalliseParams): SkillRecord | null;
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ // AMD-02 SKILL BANK — P0-SKILL2 — Skill crystallisation pipeline
3
+ // Called after each APPROVED task to distil execution into a reusable skill record
4
+ // Phase 1: write to skill-bank/kognai-owned/. Phase 3: expose via marketplace.
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.crystalliseSkill = crystalliseSkill;
7
+ const fs_1 = require("fs");
8
+ const path_1 = require("path");
9
+ const engine_paths_1 = require("./engine-paths");
10
+ const ROOT = (0, engine_paths_1.resolveEnginePaths)().root;
11
+ const SKILL_BANK_DIR = (0, path_1.join)(ROOT, 'skill-bank/kognai-owned');
12
+ function crystalliseSkill(params) {
13
+ if (params.score < 75)
14
+ return null; // Only crystallise high-quality executions
15
+ const slug = params.taskTitle
16
+ .toLowerCase()
17
+ .replace(/[^a-z0-9]+/g, '-')
18
+ .replace(/^-|-$/g, '')
19
+ .substring(0, 40);
20
+ const skill_id = `${params.agentId}-${params.sprintId}-${slug}`;
21
+ const now = new Date().toISOString();
22
+ const skillPath = (0, path_1.join)(SKILL_BANK_DIR, `${skill_id}.json`);
23
+ // If skill already exists, append score to history and update
24
+ if ((0, fs_1.existsSync)(skillPath)) {
25
+ const existing = JSON.parse((0, fs_1.readFileSync)(skillPath, 'utf-8'));
26
+ existing.score_history.push({ sprint_id: params.sprintId, task_id: params.taskId, score: params.score, reviewed_at: now });
27
+ existing.execution_count += 1;
28
+ existing.updated_at = now;
29
+ (0, fs_1.writeFileSync)(skillPath, JSON.stringify(existing, null, 2), 'utf-8');
30
+ return existing;
31
+ }
32
+ const record = {
33
+ skill_id,
34
+ type: 'kognai-owned',
35
+ name: params.taskTitle.substring(0, 60),
36
+ description: params.approachSummary.substring(0, 200),
37
+ definition: {
38
+ approach: params.approachSummary,
39
+ key_patterns: params.keyPatterns.slice(0, 5),
40
+ anti_patterns: params.antiPatterns.slice(0, 3),
41
+ },
42
+ optimal_settings: {
43
+ model: params.model,
44
+ task_target: params.taskTarget,
45
+ max_attempts: 3,
46
+ },
47
+ score_history: [{ sprint_id: params.sprintId, task_id: params.taskId, score: params.score, reviewed_at: now }],
48
+ execution_count: 1,
49
+ access_tier: 'internal',
50
+ source_sprint: params.sprintId,
51
+ source_task: params.taskId,
52
+ agent_id: params.agentId,
53
+ created_at: now,
54
+ updated_at: now,
55
+ };
56
+ if (!(0, fs_1.existsSync)(SKILL_BANK_DIR))
57
+ (0, fs_1.mkdirSync)(SKILL_BANK_DIR, { recursive: true });
58
+ (0, fs_1.writeFileSync)(skillPath, JSON.stringify(record, null, 2), 'utf-8');
59
+ return record;
60
+ }
@@ -0,0 +1,27 @@
1
+ /**
2
+ * sprint-runner.ts — Auto-executes pending sprint tasks via dual-supervisor orchestrator
3
+ *
4
+ * PM2 cron: every 30 minutes — checks for pending work and runs it
5
+ *
6
+ * Flow:
7
+ * 1. Check lock file (prevents parallel sprints)
8
+ * 2. Scan sprints/ for JSON files with pending tasks
9
+ * Priority: week-N.json descending (newest sprint first)
10
+ * 3. Read sprint JSON, inject sprint_id into each task
11
+ * 4. Write modified sprint to logs/sprint-runner-active.json
12
+ * 5. Spawn orchestrate-agents-v2.ts on the temp ACTIVE file
13
+ * (Dual supervisor: Claude Sonnet + OpenAI Codex, CEO conflict resolution)
14
+ * 6. Telegram alert on start + finish
15
+ * 7. Release lock when done
16
+ *
17
+ * GitHub Issues → Sprint Tasks:
18
+ * CEO creates GitHub issues as directives. To execute them, they must be
19
+ * converted into a sprint JSON file (sprints/week-N.json) first.
20
+ * The CEO bot or a human writes the sprint JSON; this runner executes it.
21
+ */
22
+ export interface SprintRunnerOpts {
23
+ orchestratorScript: string;
24
+ postSprintHook?: () => void;
25
+ }
26
+ declare function runSprintCycle(opts: SprintRunnerOpts): Promise<void>;
27
+ export { runSprintCycle };