haansi 0.1.44 → 0.1.46
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/dist/haansi.js +1190 -37
- package/package.json +1 -1
package/dist/haansi.js
CHANGED
|
@@ -95,7 +95,7 @@ var require_package = __commonJS({
|
|
|
95
95
|
"package.json"(exports2, module2) {
|
|
96
96
|
module2.exports = {
|
|
97
97
|
name: "haansi",
|
|
98
|
-
version: "0.1.
|
|
98
|
+
version: "0.1.46",
|
|
99
99
|
description: "Haansi CLI - Session collector and MCP server for Claude Code & OpenAI Codex",
|
|
100
100
|
bin: {
|
|
101
101
|
haansi: "./dist/haansi.js"
|
|
@@ -958,12 +958,24 @@ function normKey(key) {
|
|
|
958
958
|
function isSensitiveKey(key) {
|
|
959
959
|
return SENSITIVE_KEY_RE.test(normKey(key));
|
|
960
960
|
}
|
|
961
|
+
function isUserContentKey(key) {
|
|
962
|
+
return USER_CONTENT_KEY_RE.test(normKey(key));
|
|
963
|
+
}
|
|
964
|
+
function redactUserContent(value) {
|
|
965
|
+
if (typeof value === "string") return `[REDACTED ${value.length} chars]`;
|
|
966
|
+
if (Array.isArray(value)) return `[REDACTED ${value.length} items]`;
|
|
967
|
+
if (value === null || value === void 0) return value;
|
|
968
|
+
if (typeof value === "object") return "[REDACTED]";
|
|
969
|
+
return value;
|
|
970
|
+
}
|
|
961
971
|
function sanitizeMetadata(obj, depth = 0) {
|
|
962
972
|
if (depth > 5) return obj;
|
|
963
973
|
const result = {};
|
|
964
974
|
for (const [k, v] of Object.entries(obj)) {
|
|
965
975
|
if (isSensitiveKey(k)) {
|
|
966
976
|
result[k] = "[REDACTED]";
|
|
977
|
+
} else if (isUserContentKey(k)) {
|
|
978
|
+
result[k] = redactUserContent(v);
|
|
967
979
|
} else if (v !== null && typeof v === "object" && !Array.isArray(v) && !(v instanceof Date)) {
|
|
968
980
|
result[k] = sanitizeMetadata(v, depth + 1);
|
|
969
981
|
} else {
|
|
@@ -972,6 +984,17 @@ function sanitizeMetadata(obj, depth = 0) {
|
|
|
972
984
|
}
|
|
973
985
|
return result;
|
|
974
986
|
}
|
|
987
|
+
function causeForFirstLine(metadata) {
|
|
988
|
+
const error2 = metadata?.error;
|
|
989
|
+
const raw = typeof error2 === "string" ? error2 : error2 && typeof error2 === "object" ? error2.message : void 0;
|
|
990
|
+
if (typeof raw !== "string") return "";
|
|
991
|
+
const text = raw.replace(/\s+/g, " ").trim();
|
|
992
|
+
if (!text) return "";
|
|
993
|
+
const name = error2 && typeof error2 === "object" ? error2.name : void 0;
|
|
994
|
+
const kind = typeof name === "string" && name && name !== "Error" ? `${name}: ` : "";
|
|
995
|
+
const words = text.length > FIRST_LINE_CAUSE_CHARS ? `${text.slice(0, FIRST_LINE_CAUSE_CHARS - 1)}\u2026` : text;
|
|
996
|
+
return ` \u2014 ${kind}${words}`;
|
|
997
|
+
}
|
|
975
998
|
function normalizeErrorMetadata(error2, metadata) {
|
|
976
999
|
if (!error2) return metadata;
|
|
977
1000
|
if (error2 instanceof Error) {
|
|
@@ -998,7 +1021,7 @@ function createLogger(serviceName, projectId) {
|
|
|
998
1021
|
projectId === null ? void 0 : projectId || process.env.GCP_PROJECT_ID
|
|
999
1022
|
);
|
|
1000
1023
|
}
|
|
1001
|
-
var import_async_hooks, _cloudBackend, SENSITIVE_KEY_RE, traceStorage, StructuredLogger, TraceContext;
|
|
1024
|
+
var import_async_hooks, _cloudBackend, SENSITIVE_KEY_RE, USER_CONTENT_KEY_RE, FIRST_LINE_CAUSE_CHARS, traceStorage, StructuredLogger, TraceContext;
|
|
1002
1025
|
var init_logger = __esm({
|
|
1003
1026
|
"../../packages/@company/observability/src/logger.ts"() {
|
|
1004
1027
|
"use strict";
|
|
@@ -1006,6 +1029,8 @@ var init_logger = __esm({
|
|
|
1006
1029
|
init_esm_node();
|
|
1007
1030
|
init_types();
|
|
1008
1031
|
SENSITIVE_KEY_RE = /^(password|passwd|secret|token|apikey|authorization|auth|authtoken|authkey|credentials?|connectionstring|privatekey)$/;
|
|
1032
|
+
USER_CONTENT_KEY_RE = /^(question|questiontext|query|querytext|q|searchquery|searchtext|searchterm|searchterms|userquery|prompt|userprompt|usermessage|messagetext|messagecontent)$/;
|
|
1033
|
+
FIRST_LINE_CAUSE_CHARS = 300;
|
|
1009
1034
|
traceStorage = new import_async_hooks.AsyncLocalStorage();
|
|
1010
1035
|
StructuredLogger = class {
|
|
1011
1036
|
serviceName;
|
|
@@ -1061,7 +1086,7 @@ var init_logger = __esm({
|
|
|
1061
1086
|
const traceInfo = entry2.traceId ? ` [trace: ${entry2.traceId.slice(0, 8)}]` : "";
|
|
1062
1087
|
const orgInfo = entry2.organizationId ? ` [org: ${entry2.organizationId.slice(0, 8)}]` : "";
|
|
1063
1088
|
const prefix = `[${timestamp}] [${entry2.severity}] [${this.serviceName}]${traceInfo}${orgInfo}`;
|
|
1064
|
-
const message = `${prefix} ${entry2.message}`;
|
|
1089
|
+
const message = `${prefix} ${entry2.message}${causeForFirstLine(entry2.metadata)}`;
|
|
1065
1090
|
const metadata = entry2.metadata ? `
|
|
1066
1091
|
${JSON.stringify(entry2.metadata, null, 2)}` : "";
|
|
1067
1092
|
switch (entry2.severity) {
|
|
@@ -1699,6 +1724,22 @@ var init_scaling_metrics = __esm({
|
|
|
1699
1724
|
treatMissingData: "breaching",
|
|
1700
1725
|
missingDataRationale: "The reconciler is the only publisher and runs on a schedule independent of every worker. Its silence means the reconciler itself is broken, and the backlog it was watching is unobserved rather than empty. Scaling out against an unknown backlog wastes money; scaling in loses the queue. Breaching keeps capacity up until a human looks."
|
|
1701
1726
|
}),
|
|
1727
|
+
MINING_REPLAYS_IN_PROGRESS: spec({
|
|
1728
|
+
name: "haansi/mining/replays_in_progress",
|
|
1729
|
+
unit: "Count",
|
|
1730
|
+
description: "Orgs whose mining is held by a re-run (hard reset or re-mine): organization_mining_config.rerun_in_progress.",
|
|
1731
|
+
dimensions: ["environment"],
|
|
1732
|
+
treatMissingData: "breaching",
|
|
1733
|
+
missingDataRationale: "A re-run embeds and classifies every event through Presidio and the embedders, but it is not request-driven, so nothing else marks those services busy while it runs. Silence means the reconciler failed, not that no re-run is running; breaching keeps them awake."
|
|
1734
|
+
}),
|
|
1735
|
+
REPLAY_PENDING_EVENTS: spec({
|
|
1736
|
+
name: "haansi/replay/pending_events",
|
|
1737
|
+
unit: "Count",
|
|
1738
|
+
description: "source_events a RUNNING re-run (live hard-reset lease) has yet to replay, past its watermark, all orgs.",
|
|
1739
|
+
dimensions: ["environment"],
|
|
1740
|
+
treatMissingData: "breaching",
|
|
1741
|
+
missingDataRationale: "A re-run embeds every event inline through the batch embedders, but those rows are already normalized and never become claims, so neither backlog_rows nor claims_pending nor canonical_backlog_events can see the demand: one TEI task served a whole re-run at ~1 s/text (dev 2026-10-06). This is the only publisher of that demand; silence means it is unobserved, not finished. Breaching keeps the embedders up."
|
|
1742
|
+
}),
|
|
1702
1743
|
CANONICAL_BACKLOG_OLDEST_SECONDS: spec({
|
|
1703
1744
|
name: "haansi/ingestion/canonical_backlog_oldest_seconds",
|
|
1704
1745
|
unit: "Seconds",
|
|
@@ -2130,11 +2171,19 @@ var init_detect = __esm({
|
|
|
2130
2171
|
}
|
|
2131
2172
|
});
|
|
2132
2173
|
|
|
2174
|
+
// ../../packages/@company/encryption/src/org-binding.ts
|
|
2175
|
+
var init_org_binding = __esm({
|
|
2176
|
+
"../../packages/@company/encryption/src/org-binding.ts"() {
|
|
2177
|
+
"use strict";
|
|
2178
|
+
}
|
|
2179
|
+
});
|
|
2180
|
+
|
|
2133
2181
|
// ../../packages/@company/encryption/src/org-keys.ts
|
|
2134
2182
|
var DEK_CACHE_TTL_MS, DEK_CACHE_MAX, HKDF_SALT;
|
|
2135
2183
|
var init_org_keys = __esm({
|
|
2136
2184
|
"../../packages/@company/encryption/src/org-keys.ts"() {
|
|
2137
2185
|
"use strict";
|
|
2186
|
+
init_org_binding();
|
|
2138
2187
|
DEK_CACHE_TTL_MS = Number(
|
|
2139
2188
|
process.env.ORG_DEK_CACHE_TTL_MS ?? 10 * 6e4
|
|
2140
2189
|
);
|
|
@@ -16363,6 +16412,98 @@ var init_redis_client = __esm({
|
|
|
16363
16412
|
}
|
|
16364
16413
|
});
|
|
16365
16414
|
|
|
16415
|
+
// ../../packages/@company/security/src/service-delegation.ts
|
|
16416
|
+
var ORG, SERVICE_INTELLIGENCE_RULES;
|
|
16417
|
+
var init_service_delegation = __esm({
|
|
16418
|
+
"../../packages/@company/security/src/service-delegation.ts"() {
|
|
16419
|
+
"use strict";
|
|
16420
|
+
ORG = "[0-9a-fA-F-]{36}";
|
|
16421
|
+
SERVICE_INTELLIGENCE_RULES = [
|
|
16422
|
+
{
|
|
16423
|
+
caller: "service-capture",
|
|
16424
|
+
method: "POST",
|
|
16425
|
+
path: /^\/ingest$/,
|
|
16426
|
+
action: "ingest"
|
|
16427
|
+
},
|
|
16428
|
+
...["service-capture", "service-pipeline", "api"].map(
|
|
16429
|
+
(caller) => ({
|
|
16430
|
+
caller,
|
|
16431
|
+
method: "POST",
|
|
16432
|
+
path: /^\/replay$/,
|
|
16433
|
+
action: "replay"
|
|
16434
|
+
})
|
|
16435
|
+
),
|
|
16436
|
+
{
|
|
16437
|
+
caller: "api",
|
|
16438
|
+
method: "GET",
|
|
16439
|
+
path: new RegExp(`^/replay/${ORG}$`),
|
|
16440
|
+
action: "replay.read"
|
|
16441
|
+
},
|
|
16442
|
+
{ caller: "api", method: "GET", path: /^\/replays$/, action: "replay.read" },
|
|
16443
|
+
{
|
|
16444
|
+
caller: "api",
|
|
16445
|
+
method: "POST",
|
|
16446
|
+
path: /^\/quiesce$/,
|
|
16447
|
+
action: "mining.quiesce"
|
|
16448
|
+
},
|
|
16449
|
+
{
|
|
16450
|
+
caller: "api",
|
|
16451
|
+
method: "POST",
|
|
16452
|
+
path: /^\/resume$/,
|
|
16453
|
+
action: "mining.resume"
|
|
16454
|
+
},
|
|
16455
|
+
{
|
|
16456
|
+
caller: "service-pipeline",
|
|
16457
|
+
method: "POST",
|
|
16458
|
+
path: /^\/cron\/[a-z-]+$/,
|
|
16459
|
+
action: "cron"
|
|
16460
|
+
},
|
|
16461
|
+
{
|
|
16462
|
+
caller: "api",
|
|
16463
|
+
method: "POST",
|
|
16464
|
+
path: new RegExp(`^/processes/refresh-stats/${ORG}$`),
|
|
16465
|
+
action: "processes.refresh"
|
|
16466
|
+
},
|
|
16467
|
+
{
|
|
16468
|
+
caller: "api",
|
|
16469
|
+
method: "GET",
|
|
16470
|
+
path: new RegExp(`^/mining-config/${ORG}$`),
|
|
16471
|
+
action: "mining-config.read"
|
|
16472
|
+
},
|
|
16473
|
+
{
|
|
16474
|
+
caller: "api",
|
|
16475
|
+
method: "PATCH",
|
|
16476
|
+
path: new RegExp(`^/mining-config/${ORG}$`),
|
|
16477
|
+
action: "mining-config.write"
|
|
16478
|
+
},
|
|
16479
|
+
{
|
|
16480
|
+
caller: "api",
|
|
16481
|
+
method: "POST",
|
|
16482
|
+
path: /^\/graph\/connections$/,
|
|
16483
|
+
action: "graph.connections"
|
|
16484
|
+
},
|
|
16485
|
+
{
|
|
16486
|
+
caller: "api",
|
|
16487
|
+
method: "POST",
|
|
16488
|
+
path: /^\/on-integration$/,
|
|
16489
|
+
action: "integration.connected"
|
|
16490
|
+
},
|
|
16491
|
+
{
|
|
16492
|
+
caller: "api",
|
|
16493
|
+
method: "POST",
|
|
16494
|
+
path: /^\/debug\/classify-preview$/,
|
|
16495
|
+
action: "debug.classify"
|
|
16496
|
+
},
|
|
16497
|
+
{
|
|
16498
|
+
caller: "api",
|
|
16499
|
+
method: "GET",
|
|
16500
|
+
path: new RegExp(`^/diagnostics/${ORG}$`),
|
|
16501
|
+
action: "diagnostics.read"
|
|
16502
|
+
}
|
|
16503
|
+
];
|
|
16504
|
+
}
|
|
16505
|
+
});
|
|
16506
|
+
|
|
16366
16507
|
// ../../packages/@company/security/src/index.ts
|
|
16367
16508
|
var init_src3 = __esm({
|
|
16368
16509
|
"../../packages/@company/security/src/index.ts"() {
|
|
@@ -16372,6 +16513,7 @@ var init_src3 = __esm({
|
|
|
16372
16513
|
init_rate_limiter();
|
|
16373
16514
|
init_in_process_rate_limiter();
|
|
16374
16515
|
init_redis_client();
|
|
16516
|
+
init_service_delegation();
|
|
16375
16517
|
}
|
|
16376
16518
|
});
|
|
16377
16519
|
|
|
@@ -16384,6 +16526,7 @@ var init_decrypt_rows = __esm({
|
|
|
16384
16526
|
init_src2();
|
|
16385
16527
|
init_detect();
|
|
16386
16528
|
init_org_keys();
|
|
16529
|
+
init_org_binding();
|
|
16387
16530
|
obs2 = createObservabilityService("decrypt-rows");
|
|
16388
16531
|
}
|
|
16389
16532
|
});
|
|
@@ -16416,6 +16559,14 @@ var init_encrypt_write = __esm({
|
|
|
16416
16559
|
init_column_registry();
|
|
16417
16560
|
init_jsonb_leaf_policy();
|
|
16418
16561
|
init_hmac();
|
|
16562
|
+
init_org_binding();
|
|
16563
|
+
}
|
|
16564
|
+
});
|
|
16565
|
+
|
|
16566
|
+
// ../../packages/@company/encryption/src/write-refusal.ts
|
|
16567
|
+
var init_write_refusal = __esm({
|
|
16568
|
+
"../../packages/@company/encryption/src/write-refusal.ts"() {
|
|
16569
|
+
"use strict";
|
|
16419
16570
|
}
|
|
16420
16571
|
});
|
|
16421
16572
|
|
|
@@ -16434,22 +16585,43 @@ var init_exclusions = __esm({
|
|
|
16434
16585
|
}
|
|
16435
16586
|
});
|
|
16436
16587
|
|
|
16588
|
+
// ../../packages/@company/encryption/src/audit.ts
|
|
16589
|
+
var init_audit = __esm({
|
|
16590
|
+
"../../packages/@company/encryption/src/audit.ts"() {
|
|
16591
|
+
"use strict";
|
|
16592
|
+
init_detect();
|
|
16593
|
+
init_jsonb_leaf_policy();
|
|
16594
|
+
}
|
|
16595
|
+
});
|
|
16596
|
+
|
|
16597
|
+
// ../../packages/@company/encryption/src/rebind.ts
|
|
16598
|
+
var init_rebind = __esm({
|
|
16599
|
+
"../../packages/@company/encryption/src/rebind.ts"() {
|
|
16600
|
+
"use strict";
|
|
16601
|
+
init_detect();
|
|
16602
|
+
init_org_keys();
|
|
16603
|
+
}
|
|
16604
|
+
});
|
|
16605
|
+
|
|
16437
16606
|
// ../../packages/@company/encryption/src/org-encryption-service.ts
|
|
16438
16607
|
var init_org_encryption_service = __esm({
|
|
16439
16608
|
"../../packages/@company/encryption/src/org-encryption-service.ts"() {
|
|
16440
16609
|
"use strict";
|
|
16441
16610
|
init_src3();
|
|
16442
16611
|
init_org_keys();
|
|
16612
|
+
init_org_binding();
|
|
16443
16613
|
}
|
|
16444
16614
|
});
|
|
16445
16615
|
|
|
16446
16616
|
// ../../packages/@company/encryption/src/install-org-key-warmer.ts
|
|
16447
|
-
var WARM_TTL_MS;
|
|
16617
|
+
var import_node_async_hooks, WARM_TTL_MS, warmingInThisChain;
|
|
16448
16618
|
var init_install_org_key_warmer = __esm({
|
|
16449
16619
|
"../../packages/@company/encryption/src/install-org-key-warmer.ts"() {
|
|
16450
16620
|
"use strict";
|
|
16621
|
+
import_node_async_hooks = require("node:async_hooks");
|
|
16451
16622
|
init_org_keys();
|
|
16452
16623
|
WARM_TTL_MS = Number(process.env.ORG_KEY_WARM_TTL_MS ?? 5 * 6e4);
|
|
16624
|
+
warmingInThisChain = new import_node_async_hooks.AsyncLocalStorage();
|
|
16453
16625
|
}
|
|
16454
16626
|
});
|
|
16455
16627
|
|
|
@@ -16461,6 +16633,14 @@ var init_provision_hook = __esm({
|
|
|
16461
16633
|
}
|
|
16462
16634
|
});
|
|
16463
16635
|
|
|
16636
|
+
// ../../packages/@company/encryption/src/org-data-key-wrapper.ts
|
|
16637
|
+
var init_org_data_key_wrapper = __esm({
|
|
16638
|
+
"../../packages/@company/encryption/src/org-data-key-wrapper.ts"() {
|
|
16639
|
+
"use strict";
|
|
16640
|
+
init_org_encryption_service();
|
|
16641
|
+
}
|
|
16642
|
+
});
|
|
16643
|
+
|
|
16464
16644
|
// ../../packages/@company/encryption/src/index.ts
|
|
16465
16645
|
var init_src4 = __esm({
|
|
16466
16646
|
"../../packages/@company/encryption/src/index.ts"() {
|
|
@@ -16472,13 +16652,18 @@ var init_src4 = __esm({
|
|
|
16472
16652
|
init_decrypt_rows();
|
|
16473
16653
|
init_encrypt_write();
|
|
16474
16654
|
init_write_plan();
|
|
16655
|
+
init_write_refusal();
|
|
16475
16656
|
init_jsonb_leaf_policy();
|
|
16476
16657
|
init_read_gate();
|
|
16477
16658
|
init_exclusions();
|
|
16659
|
+
init_audit();
|
|
16478
16660
|
init_org_keys();
|
|
16661
|
+
init_org_binding();
|
|
16662
|
+
init_rebind();
|
|
16479
16663
|
init_org_encryption_service();
|
|
16480
16664
|
init_install_org_key_warmer();
|
|
16481
16665
|
init_provision_hook();
|
|
16666
|
+
init_org_data_key_wrapper();
|
|
16482
16667
|
}
|
|
16483
16668
|
});
|
|
16484
16669
|
|
|
@@ -21538,12 +21723,30 @@ var init_client = __esm({
|
|
|
21538
21723
|
}
|
|
21539
21724
|
});
|
|
21540
21725
|
|
|
21726
|
+
// ../../packages/@company/db/src/listener-connection.ts
|
|
21727
|
+
var init_listener_connection = __esm({
|
|
21728
|
+
"../../packages/@company/db/src/listener-connection.ts"() {
|
|
21729
|
+
"use strict";
|
|
21730
|
+
}
|
|
21731
|
+
});
|
|
21732
|
+
|
|
21733
|
+
// ../../packages/@company/db/src/release-after-callback.ts
|
|
21734
|
+
var observability3;
|
|
21735
|
+
var init_release_after_callback = __esm({
|
|
21736
|
+
"../../packages/@company/db/src/release-after-callback.ts"() {
|
|
21737
|
+
"use strict";
|
|
21738
|
+
init_src2();
|
|
21739
|
+
observability3 = createObservabilityService("db-release-after-callback");
|
|
21740
|
+
}
|
|
21741
|
+
});
|
|
21742
|
+
|
|
21541
21743
|
// ../../packages/@company/db/src/byod/routed-pool.ts
|
|
21542
21744
|
var logger, ROUTED_TENANT_CONTEXT, ROUTED_TENANT_RAW_POOL, ADMITTED_TENANT_CONTEXT;
|
|
21543
21745
|
var init_routed_pool = __esm({
|
|
21544
21746
|
"../../packages/@company/db/src/byod/routed-pool.ts"() {
|
|
21545
21747
|
"use strict";
|
|
21546
21748
|
init_src2();
|
|
21749
|
+
init_release_after_callback();
|
|
21547
21750
|
logger = createLogger("db-byod-routed-pool");
|
|
21548
21751
|
ROUTED_TENANT_CONTEXT = Symbol.for("haansi.db.routedTenantContext");
|
|
21549
21752
|
ROUTED_TENANT_RAW_POOL = Symbol.for("haansi.db.routedTenantRawPool");
|
|
@@ -21552,18 +21755,28 @@ var init_routed_pool = __esm({
|
|
|
21552
21755
|
});
|
|
21553
21756
|
|
|
21554
21757
|
// ../../packages/@company/db/src/org-context.ts
|
|
21555
|
-
var
|
|
21758
|
+
var observability4, DECRYPTING_CLIENT;
|
|
21556
21759
|
var init_org_context = __esm({
|
|
21557
21760
|
"../../packages/@company/db/src/org-context.ts"() {
|
|
21558
21761
|
"use strict";
|
|
21559
21762
|
init_src4();
|
|
21560
21763
|
init_src2();
|
|
21561
21764
|
init_routed_pool();
|
|
21562
|
-
|
|
21765
|
+
init_release_after_callback();
|
|
21766
|
+
observability4 = createObservabilityService("db-org-context");
|
|
21563
21767
|
DECRYPTING_CLIENT = Symbol.for("haansi.db.decryptingClient");
|
|
21564
21768
|
}
|
|
21565
21769
|
});
|
|
21566
21770
|
|
|
21771
|
+
// ../../packages/@company/db/src/admin-pools.ts
|
|
21772
|
+
var init_admin_pools = __esm({
|
|
21773
|
+
"../../packages/@company/db/src/admin-pools.ts"() {
|
|
21774
|
+
"use strict";
|
|
21775
|
+
init_client();
|
|
21776
|
+
init_org_context();
|
|
21777
|
+
}
|
|
21778
|
+
});
|
|
21779
|
+
|
|
21567
21780
|
// ../../packages/@company/types/src/timeline.ts
|
|
21568
21781
|
var init_timeline = __esm({
|
|
21569
21782
|
"../../packages/@company/types/src/timeline.ts"() {
|
|
@@ -21571,6 +21784,13 @@ var init_timeline = __esm({
|
|
|
21571
21784
|
}
|
|
21572
21785
|
});
|
|
21573
21786
|
|
|
21787
|
+
// ../../packages/@company/types/src/qna.ts
|
|
21788
|
+
var init_qna = __esm({
|
|
21789
|
+
"../../packages/@company/types/src/qna.ts"() {
|
|
21790
|
+
"use strict";
|
|
21791
|
+
}
|
|
21792
|
+
});
|
|
21793
|
+
|
|
21574
21794
|
// ../../packages/@company/types/src/artifact.ts
|
|
21575
21795
|
var init_artifact = __esm({
|
|
21576
21796
|
"../../packages/@company/types/src/artifact.ts"() {
|
|
@@ -21697,12 +21917,15 @@ var init_taxonomy = __esm({
|
|
|
21697
21917
|
},
|
|
21698
21918
|
report_onboarding: {
|
|
21699
21919
|
category: "report",
|
|
21700
|
-
label: "Onboarding
|
|
21701
|
-
description: "Onboarding guide
|
|
21702
|
-
icon: "
|
|
21920
|
+
label: "Onboarding Guide",
|
|
21921
|
+
description: "Onboarding guide (or legacy onboarding packet) built from selected team knowledge. Served only after its sources are checked for the viewer; read and written only by the onboarding guide service.",
|
|
21922
|
+
icon: "Sprout",
|
|
21703
21923
|
aliases: ["onboarding_packet", "onboarding-packet"],
|
|
21704
21924
|
autoApproved: false,
|
|
21705
|
-
producedBy: ["POST /api/v1/memory/
|
|
21925
|
+
producedBy: ["POST /api/v1/memory/onboarding/guides/:id/generate"],
|
|
21926
|
+
// docs/product/plans/2026-09-24-onboarding-guides.md D11: no generic
|
|
21927
|
+
// reader or writer may touch a guide.
|
|
21928
|
+
reserved: true
|
|
21706
21929
|
},
|
|
21707
21930
|
report_pr: {
|
|
21708
21931
|
category: "report",
|
|
@@ -21711,7 +21934,9 @@ var init_taxonomy = __esm({
|
|
|
21711
21934
|
icon: "GitPullRequest",
|
|
21712
21935
|
aliases: ["pr_context", "pr-context"],
|
|
21713
21936
|
autoApproved: true,
|
|
21714
|
-
|
|
21937
|
+
// PR generation is parked until workstream-backed context retrieval exists.
|
|
21938
|
+
// producedBy: ["POST /api/v1/memory/reports/pr"],
|
|
21939
|
+
producedBy: []
|
|
21715
21940
|
},
|
|
21716
21941
|
expert: {
|
|
21717
21942
|
category: "expert",
|
|
@@ -21742,6 +21967,18 @@ var init_taxonomy = __esm({
|
|
|
21742
21967
|
autoApproved: true,
|
|
21743
21968
|
producedBy: ["POST /api/v1/memory/recall/messages/:id/feedback"]
|
|
21744
21969
|
},
|
|
21970
|
+
skill: {
|
|
21971
|
+
category: "solution",
|
|
21972
|
+
label: "Skill",
|
|
21973
|
+
description: "Reusable, agent-loadable procedure in SKILL.md form, skillified from mined solutions or imported. One immutable revision per row; lifecycle and access live in the skills tables and are applied only by the skill service.",
|
|
21974
|
+
icon: "Wand2",
|
|
21975
|
+
aliases: ["skills", "playbook"],
|
|
21976
|
+
autoApproved: false,
|
|
21977
|
+
producedBy: [],
|
|
21978
|
+
// docs/product/plans/2026-10-10-memory-skills.md §3.1: no generic reader
|
|
21979
|
+
// or writer may touch a skill revision.
|
|
21980
|
+
reserved: true
|
|
21981
|
+
},
|
|
21745
21982
|
digest_entry: {
|
|
21746
21983
|
category: "digest",
|
|
21747
21984
|
label: "Digest Entry",
|
|
@@ -21832,16 +22069,825 @@ var init_report_template = __esm({
|
|
|
21832
22069
|
}
|
|
21833
22070
|
});
|
|
21834
22071
|
|
|
22072
|
+
// ../../packages/@company/types/src/mining-config-fields.ts
|
|
22073
|
+
var MINING_FIELDS, MINING_PARAMETER_FIELDS, MINING_BUILTIN_DEFAULTS, MINING_FIELDS_BY_KEY;
|
|
22074
|
+
var init_mining_config_fields = __esm({
|
|
22075
|
+
"../../packages/@company/types/src/mining-config-fields.ts"() {
|
|
22076
|
+
"use strict";
|
|
22077
|
+
MINING_FIELDS = [
|
|
22078
|
+
{
|
|
22079
|
+
key: "matcher_mode",
|
|
22080
|
+
camel: "matcherMode",
|
|
22081
|
+
label: "Matcher mode",
|
|
22082
|
+
kind: "select",
|
|
22083
|
+
group: "matcher",
|
|
22084
|
+
options: ["heuristic", "classifier"],
|
|
22085
|
+
help: "Heuristic score vs the trained event-pair classifier. Classifier requires a version.",
|
|
22086
|
+
platformDefault: false
|
|
22087
|
+
},
|
|
22088
|
+
{
|
|
22089
|
+
key: "classifier_name",
|
|
22090
|
+
camel: "classifierName",
|
|
22091
|
+
label: "Classifier model",
|
|
22092
|
+
kind: "text",
|
|
22093
|
+
group: "classifier",
|
|
22094
|
+
help: "Model name served by ml-inference (default event-pair-classifier)."
|
|
22095
|
+
},
|
|
22096
|
+
{
|
|
22097
|
+
key: "pair_cap_graph",
|
|
22098
|
+
camel: "pairCapGraph",
|
|
22099
|
+
label: "Pair candidates \u2014 graph",
|
|
22100
|
+
kind: "number",
|
|
22101
|
+
group: "sampling",
|
|
22102
|
+
min: 0,
|
|
22103
|
+
max: 1e3,
|
|
22104
|
+
integer: true,
|
|
22105
|
+
help: "Candidate pairs sampled per feedback event from graph neighbours. Raising it produces more labels per event and a denser training set; lowering it keeps materialization cheap.",
|
|
22106
|
+
default: 4
|
|
22107
|
+
},
|
|
22108
|
+
{
|
|
22109
|
+
key: "pair_cap_temporal",
|
|
22110
|
+
camel: "pairCapTemporal",
|
|
22111
|
+
label: "Pair candidates \u2014 temporal",
|
|
22112
|
+
kind: "number",
|
|
22113
|
+
group: "sampling",
|
|
22114
|
+
min: 0,
|
|
22115
|
+
max: 1e3,
|
|
22116
|
+
integer: true,
|
|
22117
|
+
help: "Candidate pairs sampled per feedback event from temporal neighbours.",
|
|
22118
|
+
default: 4
|
|
22119
|
+
},
|
|
22120
|
+
{
|
|
22121
|
+
key: "pair_cap_object",
|
|
22122
|
+
camel: "pairCapObject",
|
|
22123
|
+
label: "Pair candidates \u2014 object",
|
|
22124
|
+
kind: "number",
|
|
22125
|
+
group: "sampling",
|
|
22126
|
+
min: 0,
|
|
22127
|
+
max: 1e3,
|
|
22128
|
+
integer: true,
|
|
22129
|
+
help: "Candidate pairs sampled per feedback event from shared-object neighbours.",
|
|
22130
|
+
default: 4
|
|
22131
|
+
},
|
|
22132
|
+
{
|
|
22133
|
+
key: "pair_cap_random",
|
|
22134
|
+
camel: "pairCapRandom",
|
|
22135
|
+
label: "Pair candidates \u2014 random",
|
|
22136
|
+
kind: "number",
|
|
22137
|
+
group: "sampling",
|
|
22138
|
+
min: 0,
|
|
22139
|
+
max: 1e3,
|
|
22140
|
+
integer: true,
|
|
22141
|
+
help: "Random candidate pairs per feedback event. These are the cheap negatives that keep the model from learning only from near-misses.",
|
|
22142
|
+
default: 2
|
|
22143
|
+
},
|
|
22144
|
+
{
|
|
22145
|
+
key: "test_component_size_guard",
|
|
22146
|
+
camel: "testComponentSizeGuard",
|
|
22147
|
+
label: "Holdout component size guard",
|
|
22148
|
+
kind: "number",
|
|
22149
|
+
group: "sampling",
|
|
22150
|
+
min: 1,
|
|
22151
|
+
help: "How much larger than its quota a connected component may be and still be taken for test or golden. Holdout allocation moves whole components, so without a ceiling one oversized component can swallow the training set. Raising it makes holdouts easier to fill on a corpus where labels have fused into few large components; lowering it protects train.",
|
|
22152
|
+
default: 5
|
|
22153
|
+
},
|
|
22154
|
+
{
|
|
22155
|
+
key: "min_new_labels",
|
|
22156
|
+
camel: "minNewLabels",
|
|
22157
|
+
label: "Retrain \u2014 min new labels (any split)",
|
|
22158
|
+
kind: "number",
|
|
22159
|
+
group: "sampling",
|
|
22160
|
+
min: 0,
|
|
22161
|
+
max: 1e6,
|
|
22162
|
+
integer: true,
|
|
22163
|
+
help: "Cheap pre-filter before the TRAIN-split floors are evaluated: this many new labels of any kind must have landed since the last completed run. The train-specific floors below are what actually decide whether a retrain is worth running.",
|
|
22164
|
+
default: 50
|
|
22165
|
+
},
|
|
22166
|
+
{
|
|
22167
|
+
key: "min_new_train_labels",
|
|
22168
|
+
camel: "minNewTrainLabels",
|
|
22169
|
+
label: "Retrain \u2014 min new train labels",
|
|
22170
|
+
kind: "number",
|
|
22171
|
+
group: "sampling",
|
|
22172
|
+
min: 0,
|
|
22173
|
+
max: 1e6,
|
|
22174
|
+
integer: true,
|
|
22175
|
+
help: "New TRAIN-split labels required before a retrain is queued. Deliberately separate from materialization, which drains feedback continuously \u2014 new eval/test rows change what a run is measured on, not what it can learn from, so they never trigger one. Mirrors the floor the trainer itself enforces, so the trigger does not enqueue runs the trainer will reject.",
|
|
22176
|
+
default: 400
|
|
22177
|
+
},
|
|
22178
|
+
{
|
|
22179
|
+
key: "min_new_train_positive",
|
|
22180
|
+
camel: "minNewTrainPositive",
|
|
22181
|
+
label: "Retrain \u2014 min new positives",
|
|
22182
|
+
kind: "number",
|
|
22183
|
+
group: "sampling",
|
|
22184
|
+
min: 0,
|
|
22185
|
+
max: 1e6,
|
|
22186
|
+
integer: true,
|
|
22187
|
+
help: "New TRAIN positives required before a retrain is queued.",
|
|
22188
|
+
default: 200
|
|
22189
|
+
},
|
|
22190
|
+
{
|
|
22191
|
+
key: "min_new_train_negative",
|
|
22192
|
+
camel: "minNewTrainNegative",
|
|
22193
|
+
label: "Retrain \u2014 min new negatives",
|
|
22194
|
+
kind: "number",
|
|
22195
|
+
group: "sampling",
|
|
22196
|
+
min: 0,
|
|
22197
|
+
max: 1e6,
|
|
22198
|
+
integer: true,
|
|
22199
|
+
help: "New TRAIN negatives required before a retrain is queued. Negatives are usually the scarce side, so this is the floor most likely to gate retraining.",
|
|
22200
|
+
default: 30
|
|
22201
|
+
},
|
|
22202
|
+
{
|
|
22203
|
+
key: "retrain_growth_fraction",
|
|
22204
|
+
camel: "retrainGrowthFraction",
|
|
22205
|
+
label: "Retrain \u2014 growth fraction",
|
|
22206
|
+
kind: "number",
|
|
22207
|
+
group: "sampling",
|
|
22208
|
+
min: 0,
|
|
22209
|
+
max: 1,
|
|
22210
|
+
help: "Extra new TRAIN data required, as a fraction of what the LAST COMPLETED run trained on. A flat floor has a mature org retraining forever for negligible gain: 100 new rows on top of 200 can move a model, on top of 20,000 they cannot. 0.25 means 'retrain once the training set has grown by a quarter', giving roughly logarithmic retrain frequency. 0 disables escalation and keeps the flat floors.",
|
|
22211
|
+
default: 0.25
|
|
22212
|
+
},
|
|
22213
|
+
{
|
|
22214
|
+
key: "max_new_train_labels",
|
|
22215
|
+
camel: "maxNewTrainLabels",
|
|
22216
|
+
label: "Retrain \u2014 max new labels (cap)",
|
|
22217
|
+
kind: "number",
|
|
22218
|
+
group: "sampling",
|
|
22219
|
+
min: 0,
|
|
22220
|
+
max: 1e6,
|
|
22221
|
+
integer: true,
|
|
22222
|
+
help: "Ceiling on the escalated requirement, as a budget on TOTAL new train labels. Without it a percentage of a large corpus stops being achievable \u2014 25% of 500k is 125,000 new human labels, which no org produces, so the org silently stops retraining. The per-class bars take shares of this budget apportioned by the corpus class mix, rather than each demanding the full cap. 0 removes the cap.",
|
|
22223
|
+
default: 2e3
|
|
22224
|
+
},
|
|
22225
|
+
{
|
|
22226
|
+
key: "train_lookback_days",
|
|
22227
|
+
camel: "trainLookbackDays",
|
|
22228
|
+
label: "Train lookback (days)",
|
|
22229
|
+
kind: "number",
|
|
22230
|
+
group: "sampling",
|
|
22231
|
+
min: 0,
|
|
22232
|
+
max: 1e5,
|
|
22233
|
+
integer: true,
|
|
22234
|
+
help: "How far back the TRAIN split may reach. Older labels age out of training, so the corpus stops growing without bound and the retrain growth bar plateaus instead of escalating past what an org can ever label. Applied to train ONLY: eval/test/golden keep every label, because the snapshot id is a hash of the evaluated set and ranking versions is only meaningful within a snapshot \u2014 a sliding holdout would score each version against different data. 0 disables the window. Note that shrinking this can push a split back under the per-class floors and stop training entirely, since rare classes thin out first.",
|
|
22235
|
+
default: 365
|
|
22236
|
+
},
|
|
22237
|
+
{
|
|
22238
|
+
key: "classifier_accept_min_f1",
|
|
22239
|
+
camel: "classifierAcceptMinF1",
|
|
22240
|
+
label: "Accept classifier \u2014 min best F1",
|
|
22241
|
+
kind: "number",
|
|
22242
|
+
group: "classifier",
|
|
22243
|
+
min: 0,
|
|
22244
|
+
max: 1,
|
|
22245
|
+
help: "A classifier must reach at least this best-F1 on the evaluated snapshot before it can be promoted and take over from the heuristic matcher. Measured at the model's OWN best threshold, not at 0.5, so an uncalibrated model is judged on its ranking rather than on where the cut happens to sit. This is an absolute floor \u2014 'better than the incumbent' is already enforced by the rank gate.",
|
|
22246
|
+
default: 0.75
|
|
22247
|
+
},
|
|
22248
|
+
{
|
|
22249
|
+
key: "classifier_accept_min_pr_auc",
|
|
22250
|
+
camel: "classifierAcceptMinPrAuc",
|
|
22251
|
+
label: "Accept classifier \u2014 min PR-AUC",
|
|
22252
|
+
kind: "number",
|
|
22253
|
+
group: "classifier",
|
|
22254
|
+
min: 0,
|
|
22255
|
+
max: 1,
|
|
22256
|
+
help: "Minimum average precision (PR-AUC) before a classifier can be promoted. Threshold-free, so it measures ranking quality independently of any operating point.",
|
|
22257
|
+
default: 0.8
|
|
22258
|
+
},
|
|
22259
|
+
{
|
|
22260
|
+
key: "global_classifier_versions",
|
|
22261
|
+
camel: "globalClassifierVersions",
|
|
22262
|
+
label: "Global classifier catalog",
|
|
22263
|
+
kind: "text",
|
|
22264
|
+
group: "classifier",
|
|
22265
|
+
help: "Comma-separated versions offered to orgs that have not trained their own model yet \u2014 the cold-start candidates evaluated against an org's labels once it has enough of them. Blank means every version in the model bucket is a candidate, including half-finished experiments, so setting this is how you curate. A version an org has already adopted is always kept even if it is not listed, so editing this cannot drop the model currently deciding; and a version an org archives is dropped for that org only, never globally."
|
|
22266
|
+
},
|
|
22267
|
+
{
|
|
22268
|
+
key: "classifier_version",
|
|
22269
|
+
camel: "classifierVersion",
|
|
22270
|
+
label: "Classifier version",
|
|
22271
|
+
kind: "select",
|
|
22272
|
+
group: "classifier",
|
|
22273
|
+
help: "Required when mode = classifier. Choices come from the model versions in S3.",
|
|
22274
|
+
platformDefault: false
|
|
22275
|
+
},
|
|
22276
|
+
{
|
|
22277
|
+
key: "classifier_precision_target",
|
|
22278
|
+
camel: "classifierPrecisionTarget",
|
|
22279
|
+
label: "Attach precision target",
|
|
22280
|
+
kind: "number",
|
|
22281
|
+
group: "classifier",
|
|
22282
|
+
min: 0,
|
|
22283
|
+
max: 1,
|
|
22284
|
+
help: "Minimum precision required to attach automatically. The score cutoff is DERIVED from this against each version's own test evaluation \u2014 the lowest cut that still meets the target, so recall is not given away. Set what error rate you accept (0.97 = at most three wrong links in a hundred); the number that implements it changes every retrain, because the same score means different things on different models. If a version cannot reach this precision at any cut, no attach threshold is installed and the previous one stands.",
|
|
22285
|
+
default: 0.97
|
|
22286
|
+
},
|
|
22287
|
+
{
|
|
22288
|
+
key: "classifier_review_precision_target",
|
|
22289
|
+
camel: "classifierReviewPrecisionTarget",
|
|
22290
|
+
label: "Review precision target",
|
|
22291
|
+
kind: "number",
|
|
22292
|
+
group: "classifier",
|
|
22293
|
+
min: 0,
|
|
22294
|
+
max: 1,
|
|
22295
|
+
help: "Minimum precision required to send a candidate to the LLM rather than reject it outright. Must be at or below the attach target \u2014 scores between the two cuts are the ambiguous middle the LLM adjudicates. A value above the attach target would make that band empty and silently remove the LLM safety net, so it is clamped down to the attach target.",
|
|
22296
|
+
default: 0.93
|
|
22297
|
+
},
|
|
22298
|
+
{
|
|
22299
|
+
key: "seed_aggregation",
|
|
22300
|
+
camel: "seedAggregation",
|
|
22301
|
+
label: "Seed discovery \u2014 score aggregation",
|
|
22302
|
+
kind: "select",
|
|
22303
|
+
group: "classifier",
|
|
22304
|
+
options: ["mean", "median", "max", "min", "trimmed_mean"],
|
|
22305
|
+
help: "How a candidate's per-seed pair scores collapse to one number when a curator asks for related events on /timelines. mean makes every seed vote, so a candidate has to resemble the seed set rather than any one seed; median is the outlier-tolerant version of that. max asks only 'is there a seed this candidate clearly belongs with?' \u2014 it keeps the score on the per-pair scale the attach cut was calibrated on, but one coincidental neighbour is enough to pull a candidate in. min demands every seed agree; trimmed_mean drops the weakest seed, then averages. Blank uses the built-in default (mean)."
|
|
22306
|
+
},
|
|
22307
|
+
{
|
|
22308
|
+
key: "seed_expansion_paths",
|
|
22309
|
+
camel: "seedExpansionPaths",
|
|
22310
|
+
label: "Seed discovery \u2014 candidate paths",
|
|
22311
|
+
kind: "select",
|
|
22312
|
+
group: "classifier",
|
|
22313
|
+
options: ["graph", "graph_objects", "graph_objects_semantic"],
|
|
22314
|
+
help: "Which paths find candidates when a curator asks for related events. graph walks activity_graph_edges only. The object and semantic paths mirror how the miner finds candidates, but the miner scores them against an established process; a curator-seeded set has no such history, so those paths mostly surface events that merely share a busy channel, a repo or a topic \u2014 they inflate the list without changing what gets approved. Widen only for an org whose graph is too thin to surface anything at all; the per-path counts in the discovery note tell you which one is empty. Blank uses the built-in default (graph)."
|
|
22315
|
+
},
|
|
22316
|
+
{
|
|
22317
|
+
key: "seed_llm_defer_top_n",
|
|
22318
|
+
camel: "seedLlmDeferTopN",
|
|
22319
|
+
label: "Seed discovery \u2014 LLM adjudication (top N)",
|
|
22320
|
+
kind: "number",
|
|
22321
|
+
group: "classifier",
|
|
22322
|
+
min: 0,
|
|
22323
|
+
integer: true,
|
|
22324
|
+
help: "How many ambiguous-band candidates (score between the review and attach cuts) are sent to the LLM per 'find related events' click. The band is exactly where the classifier says 'not confident either way', so something other than a number has to decide; the LLM sees the seed set once and rules on all N in a single call. The curator is waiting, so this is a latency and cost budget as much as a quality knob. 0 disables adjudication and leaves band candidates unapproved. Blank uses the built-in default (10). Requires the org to have a reasoning model configured."
|
|
22325
|
+
},
|
|
22326
|
+
{
|
|
22327
|
+
key: "classifier_max_second_hop_per_process",
|
|
22328
|
+
camel: "classifierMaxSecondHopPerProcess",
|
|
22329
|
+
label: "Max 2nd-hop / process",
|
|
22330
|
+
kind: "number",
|
|
22331
|
+
group: "classifier",
|
|
22332
|
+
min: 1,
|
|
22333
|
+
integer: true,
|
|
22334
|
+
help: "Cap on 2nd-hop neighbors scored per process. Default 8."
|
|
22335
|
+
},
|
|
22336
|
+
{
|
|
22337
|
+
key: "shadow_classifier_enabled",
|
|
22338
|
+
camel: "shadowClassifierEnabled",
|
|
22339
|
+
label: "Shadow candidate",
|
|
22340
|
+
kind: "boolean",
|
|
22341
|
+
group: "classifier",
|
|
22342
|
+
help: "Score a candidate model on live events without changing process assignment.",
|
|
22343
|
+
platformDefault: false
|
|
22344
|
+
},
|
|
22345
|
+
{
|
|
22346
|
+
key: "shadow_classifier_name",
|
|
22347
|
+
camel: "shadowClassifierName",
|
|
22348
|
+
label: "Shadow model",
|
|
22349
|
+
kind: "text",
|
|
22350
|
+
group: "classifier",
|
|
22351
|
+
help: "Candidate model name to score live in shadow mode."
|
|
22352
|
+
},
|
|
22353
|
+
{
|
|
22354
|
+
key: "shadow_classifier_version",
|
|
22355
|
+
camel: "shadowClassifierVersion",
|
|
22356
|
+
label: "Shadow version",
|
|
22357
|
+
kind: "select",
|
|
22358
|
+
group: "classifier",
|
|
22359
|
+
help: "Candidate classifier version to shadow-score before promotion.",
|
|
22360
|
+
platformDefault: false
|
|
22361
|
+
},
|
|
22362
|
+
{
|
|
22363
|
+
key: "shadow_classifier_sample_rate",
|
|
22364
|
+
camel: "shadowClassifierSampleRate",
|
|
22365
|
+
label: "Shadow sample rate",
|
|
22366
|
+
kind: "number",
|
|
22367
|
+
group: "classifier",
|
|
22368
|
+
min: 0,
|
|
22369
|
+
max: 1,
|
|
22370
|
+
help: "Fraction of live events to shadow-score with the candidate (0\u20131). Default 1."
|
|
22371
|
+
},
|
|
22372
|
+
{
|
|
22373
|
+
key: "semantic_negative_max_process_similarity",
|
|
22374
|
+
camel: "semanticNegativeMaxProcessSimilarity",
|
|
22375
|
+
label: "Negatives: max workstream similarity",
|
|
22376
|
+
kind: "number",
|
|
22377
|
+
group: "sampling",
|
|
22378
|
+
min: 0,
|
|
22379
|
+
max: 1,
|
|
22380
|
+
help: "Two workstreams must be at or below this cosine similarity before their members can be paired as negatives.",
|
|
22381
|
+
default: 0.35
|
|
22382
|
+
},
|
|
22383
|
+
{
|
|
22384
|
+
key: "semantic_negative_max_event_similarity",
|
|
22385
|
+
camel: "semanticNegativeMaxEventSimilarity",
|
|
22386
|
+
label: "Negatives: max event similarity",
|
|
22387
|
+
kind: "number",
|
|
22388
|
+
group: "sampling",
|
|
22389
|
+
min: 0,
|
|
22390
|
+
max: 1,
|
|
22391
|
+
help: "Two events must ALSO be at or below this cosine similarity to be labeled a negative. Distance at both levels is what keeps the label safe.",
|
|
22392
|
+
default: 0.35
|
|
22393
|
+
},
|
|
22394
|
+
{
|
|
22395
|
+
key: "semantic_negative_pairs_per_process_pair",
|
|
22396
|
+
camel: "semanticNegativePairsPerProcessPair",
|
|
22397
|
+
label: "Negatives: pairs per workstream pair",
|
|
22398
|
+
kind: "number",
|
|
22399
|
+
group: "sampling",
|
|
22400
|
+
min: 1,
|
|
22401
|
+
help: "Cap on negatives minted from one pair of workstreams per sweep.",
|
|
22402
|
+
default: 20
|
|
22403
|
+
},
|
|
22404
|
+
{
|
|
22405
|
+
key: "semantic_negative_max_process_pairs",
|
|
22406
|
+
camel: "semanticNegativeMaxProcessPairs",
|
|
22407
|
+
label: "Negatives: workstream pairs per sweep",
|
|
22408
|
+
kind: "number",
|
|
22409
|
+
group: "sampling",
|
|
22410
|
+
min: 1,
|
|
22411
|
+
help: "Cap on how many workstream pairs one sweep considers.",
|
|
22412
|
+
default: 40
|
|
22413
|
+
},
|
|
22414
|
+
{
|
|
22415
|
+
key: "enable_llm",
|
|
22416
|
+
camel: "enableLlm",
|
|
22417
|
+
label: "Enable LLM escalation",
|
|
22418
|
+
kind: "boolean",
|
|
22419
|
+
group: "escalation",
|
|
22420
|
+
help: "When on, ambiguous events escalate to the reasoning LLM (and it may create new processes).",
|
|
22421
|
+
platformDefault: false
|
|
22422
|
+
},
|
|
22423
|
+
{
|
|
22424
|
+
key: "heuristic_threshold_mode",
|
|
22425
|
+
camel: "heuristicThresholdMode",
|
|
22426
|
+
label: "Threshold mode",
|
|
22427
|
+
kind: "select",
|
|
22428
|
+
group: "thresholds",
|
|
22429
|
+
options: ["fixed", "calibrated"],
|
|
22430
|
+
help: "fixed: use the attach/review/reactivation values below. calibrated: mining waits until the org has enough events, then derives the three thresholds from percentiles of heuristic scores between random event pairs, and replays the org with them.",
|
|
22431
|
+
default: "fixed"
|
|
22432
|
+
},
|
|
22433
|
+
{
|
|
22434
|
+
key: "calibration_attach_percentile",
|
|
22435
|
+
camel: "calibrationAttachPercentile",
|
|
22436
|
+
label: "Attach percentile",
|
|
22437
|
+
kind: "number",
|
|
22438
|
+
group: "thresholds",
|
|
22439
|
+
minExclusive: 0,
|
|
22440
|
+
max: 1,
|
|
22441
|
+
help: "Attach threshold = this percentile of random-pair scores (0\u20131). Random pairs are mostly unrelated work, so 0.97 means about 3% of unrelated pairs would clear the bar.",
|
|
22442
|
+
default: 0.97,
|
|
22443
|
+
visibleWhen: { key: "heuristic_threshold_mode", in: ["calibrated"] }
|
|
22444
|
+
},
|
|
22445
|
+
{
|
|
22446
|
+
key: "calibration_review_percentile",
|
|
22447
|
+
camel: "calibrationReviewPercentile",
|
|
22448
|
+
label: "Review percentile",
|
|
22449
|
+
kind: "number",
|
|
22450
|
+
group: "thresholds",
|
|
22451
|
+
minExclusive: 0,
|
|
22452
|
+
max: 1,
|
|
22453
|
+
help: "Review (LLM) threshold = this percentile of random-pair scores (0\u20131). Must be below the attach percentile.",
|
|
22454
|
+
default: 0.9,
|
|
22455
|
+
visibleWhen: { key: "heuristic_threshold_mode", in: ["calibrated"] }
|
|
22456
|
+
},
|
|
22457
|
+
{
|
|
22458
|
+
key: "calibration_reactivation_percentile",
|
|
22459
|
+
camel: "calibrationReactivationPercentile",
|
|
22460
|
+
label: "Reactivation percentile",
|
|
22461
|
+
kind: "number",
|
|
22462
|
+
group: "thresholds",
|
|
22463
|
+
minExclusive: 0,
|
|
22464
|
+
max: 1,
|
|
22465
|
+
help: "Reactivation threshold = this percentile of random-pair scores (0\u20131). Must be at or above the attach percentile.",
|
|
22466
|
+
default: 0.99,
|
|
22467
|
+
visibleWhen: { key: "heuristic_threshold_mode", in: ["calibrated"] }
|
|
22468
|
+
},
|
|
22469
|
+
{
|
|
22470
|
+
key: "calibration_min_events",
|
|
22471
|
+
camel: "calibrationMinEvents",
|
|
22472
|
+
label: "Calibrate after (events)",
|
|
22473
|
+
kind: "number",
|
|
22474
|
+
group: "thresholds",
|
|
22475
|
+
min: 50,
|
|
22476
|
+
integer: true,
|
|
22477
|
+
help: "Process assignment waits until the org has this many non-noise events; then thresholds are calibrated and the org is replayed.",
|
|
22478
|
+
default: 1e3,
|
|
22479
|
+
visibleWhen: { key: "heuristic_threshold_mode", in: ["calibrated"] }
|
|
22480
|
+
},
|
|
22481
|
+
{
|
|
22482
|
+
key: "calibration_sample_pairs",
|
|
22483
|
+
camel: "calibrationSamplePairs",
|
|
22484
|
+
label: "Calibration sample pairs",
|
|
22485
|
+
kind: "number",
|
|
22486
|
+
group: "thresholds",
|
|
22487
|
+
min: 100,
|
|
22488
|
+
max: 2e4,
|
|
22489
|
+
integer: true,
|
|
22490
|
+
help: "How many random event pairs are scored. Tail percentiles need a large sample: at 2000 pairs the 99th percentile rests on ~20 scores.",
|
|
22491
|
+
default: 2e3,
|
|
22492
|
+
visibleWhen: { key: "heuristic_threshold_mode", in: ["calibrated"] }
|
|
22493
|
+
},
|
|
22494
|
+
{
|
|
22495
|
+
key: "attach_threshold",
|
|
22496
|
+
camel: "attachThreshold",
|
|
22497
|
+
label: "Attach threshold",
|
|
22498
|
+
kind: "number",
|
|
22499
|
+
group: "thresholds",
|
|
22500
|
+
min: 0,
|
|
22501
|
+
max: 1,
|
|
22502
|
+
help: "Heuristic score \u2265 this attaches the event (0\u20131). Overrides the global 0.55.",
|
|
22503
|
+
visibleWhen: { key: "heuristic_threshold_mode", in: ["fixed"] }
|
|
22504
|
+
},
|
|
22505
|
+
{
|
|
22506
|
+
key: "review_threshold",
|
|
22507
|
+
camel: "reviewThreshold",
|
|
22508
|
+
label: "Review threshold",
|
|
22509
|
+
kind: "number",
|
|
22510
|
+
group: "thresholds",
|
|
22511
|
+
min: 0,
|
|
22512
|
+
max: 1,
|
|
22513
|
+
help: "Score in [review, attach) defers to the LLM; below it starts a new context. Also the floor for name-based dedup (0\u20131). Overrides the global 0.4.",
|
|
22514
|
+
visibleWhen: { key: "heuristic_threshold_mode", in: ["fixed"] }
|
|
22515
|
+
},
|
|
22516
|
+
{
|
|
22517
|
+
key: "reactivation_threshold",
|
|
22518
|
+
camel: "reactivationThreshold",
|
|
22519
|
+
label: "Reactivation threshold",
|
|
22520
|
+
kind: "number",
|
|
22521
|
+
group: "thresholds",
|
|
22522
|
+
min: 0,
|
|
22523
|
+
max: 1,
|
|
22524
|
+
help: "Score \u2265 this reactivates a dormant context (0\u20131). Overrides the global 0.7.",
|
|
22525
|
+
visibleWhen: { key: "heuristic_threshold_mode", in: ["fixed"] }
|
|
22526
|
+
},
|
|
22527
|
+
{
|
|
22528
|
+
key: "max_attaches",
|
|
22529
|
+
camel: "maxAttaches",
|
|
22530
|
+
label: "Max attaches / event",
|
|
22531
|
+
kind: "number",
|
|
22532
|
+
group: "thresholds",
|
|
22533
|
+
min: 1,
|
|
22534
|
+
integer: true,
|
|
22535
|
+
help: "Max contexts one event attaches to. Overrides the global 5."
|
|
22536
|
+
},
|
|
22537
|
+
// ── Group B: heuristic scoring weights (null → global default) ────────────
|
|
22538
|
+
{
|
|
22539
|
+
key: "weight_entity",
|
|
22540
|
+
camel: "weightEntity",
|
|
22541
|
+
label: "Weight \xB7 entity",
|
|
22542
|
+
kind: "number",
|
|
22543
|
+
group: "weights",
|
|
22544
|
+
min: 0,
|
|
22545
|
+
max: 1,
|
|
22546
|
+
help: "Shared-object overlap weight (0\u20131). Global default 0.25. Weights should sum to ~1."
|
|
22547
|
+
},
|
|
22548
|
+
{
|
|
22549
|
+
key: "weight_author",
|
|
22550
|
+
camel: "weightAuthor",
|
|
22551
|
+
label: "Weight \xB7 author",
|
|
22552
|
+
kind: "number",
|
|
22553
|
+
group: "weights",
|
|
22554
|
+
min: 0,
|
|
22555
|
+
max: 1,
|
|
22556
|
+
help: "Same-author weight (0\u20131). Global default 0.15."
|
|
22557
|
+
},
|
|
22558
|
+
{
|
|
22559
|
+
key: "weight_temporal",
|
|
22560
|
+
camel: "weightTemporal",
|
|
22561
|
+
label: "Weight \xB7 temporal",
|
|
22562
|
+
kind: "number",
|
|
22563
|
+
group: "weights",
|
|
22564
|
+
min: 0,
|
|
22565
|
+
max: 1,
|
|
22566
|
+
help: "Time-proximity weight (0\u20131). Global default 0.10."
|
|
22567
|
+
},
|
|
22568
|
+
{
|
|
22569
|
+
key: "weight_semantic",
|
|
22570
|
+
camel: "weightSemantic",
|
|
22571
|
+
label: "Weight \xB7 semantic",
|
|
22572
|
+
kind: "number",
|
|
22573
|
+
group: "weights",
|
|
22574
|
+
min: 0,
|
|
22575
|
+
max: 1,
|
|
22576
|
+
help: "Embedding-similarity weight (0\u20131). Global default 0.35."
|
|
22577
|
+
},
|
|
22578
|
+
{
|
|
22579
|
+
key: "weight_graph",
|
|
22580
|
+
camel: "weightGraph",
|
|
22581
|
+
label: "Weight \xB7 graph",
|
|
22582
|
+
kind: "number",
|
|
22583
|
+
group: "weights",
|
|
22584
|
+
min: 0,
|
|
22585
|
+
max: 1,
|
|
22586
|
+
help: "Graph-walk signal weight (0\u20131). Global default 0.15."
|
|
22587
|
+
},
|
|
22588
|
+
{
|
|
22589
|
+
key: "idf_strength",
|
|
22590
|
+
camel: "idfStrength",
|
|
22591
|
+
label: "IDF strength",
|
|
22592
|
+
kind: "number",
|
|
22593
|
+
group: "weights",
|
|
22594
|
+
min: 0,
|
|
22595
|
+
max: 1,
|
|
22596
|
+
help: "Frequency-damping for the entity/author/graph terms (each signal weighted by 1/df^strength, df = object fan-in). 0 = off (legacy full weight); 0.5 = default; 1 = full inverse frequency. Blank = inherit global 0.5. Demotes super-node objects and a single dominant author so specific signals drive matches."
|
|
22597
|
+
},
|
|
22598
|
+
{
|
|
22599
|
+
key: "summary_embedding_decay",
|
|
22600
|
+
camel: "summaryEmbeddingDecay",
|
|
22601
|
+
label: "Summary embedding decay",
|
|
22602
|
+
kind: "number",
|
|
22603
|
+
group: "weights",
|
|
22604
|
+
min: 0.01,
|
|
22605
|
+
max: 1,
|
|
22606
|
+
help: "Recency weighting for a process's summary embedding: the newest member weighs 1, the one i events back weighs decay^i. 1 = plain mean; 0.95 = default (about 36% weight 20 events back). Blank = inherit global 0.95."
|
|
22607
|
+
},
|
|
22608
|
+
// ── Group B: object-graph edge caps + matcher budget ─────────────────────
|
|
22609
|
+
{
|
|
22610
|
+
key: "matcher_max_neighbors",
|
|
22611
|
+
camel: "matcherMaxNeighbors",
|
|
22612
|
+
label: "Matcher max neighbors",
|
|
22613
|
+
kind: "number",
|
|
22614
|
+
group: "graph",
|
|
22615
|
+
min: 1,
|
|
22616
|
+
integer: true,
|
|
22617
|
+
help: "Graph-walk neighbour budget per event. Global default 50. Raise when per-type caps thin a node's neighbourhood below this and starve candidate discovery."
|
|
22618
|
+
},
|
|
22619
|
+
{
|
|
22620
|
+
key: "matcher_min_edge_weight",
|
|
22621
|
+
camel: "matcherMinEdgeWeight",
|
|
22622
|
+
label: "Matcher min edge weight",
|
|
22623
|
+
kind: "number",
|
|
22624
|
+
group: "graph",
|
|
22625
|
+
min: 0,
|
|
22626
|
+
max: 1,
|
|
22627
|
+
help: "Weight floor for candidate edges (0\u20131). Global default 0.2."
|
|
22628
|
+
},
|
|
22629
|
+
{
|
|
22630
|
+
key: "late_event_window_hours",
|
|
22631
|
+
camel: "lateEventWindowHours",
|
|
22632
|
+
label: "Late-event window (hours)",
|
|
22633
|
+
kind: "number",
|
|
22634
|
+
group: "graph",
|
|
22635
|
+
min: 1,
|
|
22636
|
+
help: "A live event older than this (behind the org's newest processed event) is not scored inline; it waits for the windowed replay so it is scored in order. Global default 24."
|
|
22637
|
+
},
|
|
22638
|
+
{
|
|
22639
|
+
key: "max_edges_co_object",
|
|
22640
|
+
camel: "maxEdgesCoObject",
|
|
22641
|
+
label: "Cap \xB7 co_object edges",
|
|
22642
|
+
kind: "number",
|
|
22643
|
+
group: "graph",
|
|
22644
|
+
min: 1,
|
|
22645
|
+
integer: true,
|
|
22646
|
+
help: "Top-N co_object edges kept per event. Global default 5. Raising this is the durable fix for edge-cap-starved matching."
|
|
22647
|
+
},
|
|
22648
|
+
{
|
|
22649
|
+
key: "max_edges_time_neighbor",
|
|
22650
|
+
camel: "maxEdgesTimeNeighbor",
|
|
22651
|
+
label: "Cap \xB7 time_neighbor edges",
|
|
22652
|
+
kind: "number",
|
|
22653
|
+
group: "graph",
|
|
22654
|
+
min: 1,
|
|
22655
|
+
integer: true,
|
|
22656
|
+
help: "Top-N time_neighbor edges kept per event. Global default 5."
|
|
22657
|
+
},
|
|
22658
|
+
{
|
|
22659
|
+
key: "max_edges_same_semantic",
|
|
22660
|
+
camel: "maxEdgesSameSemantic",
|
|
22661
|
+
label: "Cap \xB7 same_semantic edges",
|
|
22662
|
+
kind: "number",
|
|
22663
|
+
group: "graph",
|
|
22664
|
+
min: 1,
|
|
22665
|
+
integer: true,
|
|
22666
|
+
help: "Top-N same_semantic edges kept per event. Global default 8."
|
|
22667
|
+
},
|
|
22668
|
+
{
|
|
22669
|
+
key: "max_edges_similar_authors",
|
|
22670
|
+
camel: "maxEdgesSimilarAuthors",
|
|
22671
|
+
label: "Cap \xB7 similar_authors edges",
|
|
22672
|
+
kind: "number",
|
|
22673
|
+
group: "graph",
|
|
22674
|
+
min: 1,
|
|
22675
|
+
integer: true,
|
|
22676
|
+
help: "Top-N similar_authors edges kept per event. Global default 8."
|
|
22677
|
+
},
|
|
22678
|
+
{
|
|
22679
|
+
key: "max_edges_pr_to_issue",
|
|
22680
|
+
camel: "maxEdgesPrToIssue",
|
|
22681
|
+
label: "Cap \xB7 pr_to_issue edges",
|
|
22682
|
+
kind: "number",
|
|
22683
|
+
group: "graph",
|
|
22684
|
+
min: 1,
|
|
22685
|
+
integer: true,
|
|
22686
|
+
help: "Top-N pr_to_issue edges kept per event. Global default 8."
|
|
22687
|
+
},
|
|
22688
|
+
// ─── Split allocation + training data shape (object-graph/070, /071) ──────
|
|
22689
|
+
// These existed as columns and behaviour before they existed as controls,
|
|
22690
|
+
// which meant the only way to configure a split was raw SQL — and an unset
|
|
22691
|
+
// quota silently meant "no holdout at all".
|
|
22692
|
+
{
|
|
22693
|
+
key: "golden_target_events",
|
|
22694
|
+
camel: "goldenTargetEvents",
|
|
22695
|
+
label: "Golden target (events)",
|
|
22696
|
+
kind: "number",
|
|
22697
|
+
group: "sampling",
|
|
22698
|
+
min: 1,
|
|
22699
|
+
integer: true,
|
|
22700
|
+
help: "How many EVENTS to hold out as golden. Blank derives ~5% of eligible events. Sized in events, not labels: labels are quadratic in events, so a label count overstates evaluation power. Holdout is bounded by component count \u2014 with few curated workstreams you are choosing which components, not how many events."
|
|
22701
|
+
},
|
|
22702
|
+
{
|
|
22703
|
+
key: "test_target_events",
|
|
22704
|
+
camel: "testTargetEvents",
|
|
22705
|
+
label: "Test target (events)",
|
|
22706
|
+
kind: "number",
|
|
22707
|
+
group: "sampling",
|
|
22708
|
+
min: 1,
|
|
22709
|
+
integer: true,
|
|
22710
|
+
help: "How many EVENTS to hold out as test. Blank derives ~15% of eligible events."
|
|
22711
|
+
},
|
|
22712
|
+
{
|
|
22713
|
+
key: "min_split_labels",
|
|
22714
|
+
camel: "minSplitLabels",
|
|
22715
|
+
label: "Min labels per split",
|
|
22716
|
+
kind: "number",
|
|
22717
|
+
group: "sampling",
|
|
22718
|
+
min: 0,
|
|
22719
|
+
max: 1e6,
|
|
22720
|
+
integer: true,
|
|
22721
|
+
help: "Floor each of train/eval/test must clear. Also the precondition for the golden fallback: once all three clear it, golden may take a component the size guard would otherwise refuse, so the split is never permanently empty.",
|
|
22722
|
+
default: 100
|
|
22723
|
+
},
|
|
22724
|
+
{
|
|
22725
|
+
key: "min_train_class_labels",
|
|
22726
|
+
camel: "minTrainClassLabels",
|
|
22727
|
+
label: "Min labels per class \u2014 train",
|
|
22728
|
+
kind: "number",
|
|
22729
|
+
group: "sampling",
|
|
22730
|
+
min: 0,
|
|
22731
|
+
max: 1e6,
|
|
22732
|
+
integer: true,
|
|
22733
|
+
help: "Floor EACH class must clear in the TRAIN split before fitting. This is a capacity question, not a statistical one: below roughly this many examples per class the model memorises rather than generalises. Train is also the split that can be topped up \u2014 fallback negatives are borrowed at extraction time and the set is then downsampled to balance \u2014 so it can carry a higher bar than the holdouts.",
|
|
22734
|
+
default: 200
|
|
22735
|
+
},
|
|
22736
|
+
{
|
|
22737
|
+
key: "min_eval_class_labels",
|
|
22738
|
+
camel: "minEvalClassLabels",
|
|
22739
|
+
label: "Min labels per class \u2014 eval / test",
|
|
22740
|
+
kind: "number",
|
|
22741
|
+
group: "sampling",
|
|
22742
|
+
min: 0,
|
|
22743
|
+
max: 1e6,
|
|
22744
|
+
integer: true,
|
|
22745
|
+
help: "Floor EACH class must clear in EACH of eval and test. A split can pass the total floor on volume alone and still be single-class \u2014 dev's test split held 142 labels, all positive, which any always-say-same model scores 100% on. This one is about whether a measurement means anything: a 95% interval on an observed 0.80 accuracy is roughly +/-0.14 at 30 per class and +/-0.08 at 100. Held-out splits cannot borrow negatives, so setting this above what your data can supply blocks training rather than improving it.",
|
|
22746
|
+
default: 10
|
|
22747
|
+
},
|
|
22748
|
+
{
|
|
22749
|
+
key: "label_conflict_policy",
|
|
22750
|
+
camel: "labelConflictPolicy",
|
|
22751
|
+
label: "Conflicting label policy",
|
|
22752
|
+
kind: "select",
|
|
22753
|
+
group: "sampling",
|
|
22754
|
+
options: ["keep_both", "replace", "withhold"],
|
|
22755
|
+
help: "What happens when new curation contradicts an existing human label on the same pair. keep_both (default) keeps both judgements, so training sees the ambiguity and the model is less confident there. replace supersedes the older one, for when later curation is the correction. withhold discards the new label and holds the event for review \u2014 the old behaviour, which silently dropped most removal labels."
|
|
22756
|
+
},
|
|
22757
|
+
{
|
|
22758
|
+
key: "train_negative_fallback_enabled",
|
|
22759
|
+
camel: "trainNegativeFallbackEnabled",
|
|
22760
|
+
label: "Borrow negatives for training",
|
|
22761
|
+
kind: "boolean",
|
|
22762
|
+
group: "sampling",
|
|
22763
|
+
help: "When train (or eval) has too few negatives, borrow them from sources the routing rules do not admit \u2014 typically LLM review removals. NEVER touches test or golden, and never borrows a label whose events sit in a held-out split. These are labels no human checked.",
|
|
22764
|
+
default: true
|
|
22765
|
+
},
|
|
22766
|
+
{
|
|
22767
|
+
key: "train_min_negative_share",
|
|
22768
|
+
camel: "trainMinNegativeShare",
|
|
22769
|
+
label: "Min negative share (train)",
|
|
22770
|
+
kind: "number",
|
|
22771
|
+
group: "sampling",
|
|
22772
|
+
min: 0,
|
|
22773
|
+
max: 1,
|
|
22774
|
+
help: "Below this share of negatives, the fallback engages.",
|
|
22775
|
+
default: 0.5
|
|
22776
|
+
},
|
|
22777
|
+
{
|
|
22778
|
+
key: "train_negative_fallback_max_ratio",
|
|
22779
|
+
camel: "trainNegativeFallbackMaxRatio",
|
|
22780
|
+
label: "Borrowed negatives cap (x positives)",
|
|
22781
|
+
kind: "number",
|
|
22782
|
+
group: "sampling",
|
|
22783
|
+
min: 0,
|
|
22784
|
+
help: "Ceiling on borrowed negatives as a multiple of the split's positives, so a large ineligible pool cannot swamp a small human-labelled one.",
|
|
22785
|
+
default: 1
|
|
22786
|
+
},
|
|
22787
|
+
{
|
|
22788
|
+
key: "train_balance_strategy",
|
|
22789
|
+
camel: "trainBalanceStrategy",
|
|
22790
|
+
label: "Training class balance",
|
|
22791
|
+
kind: "select",
|
|
22792
|
+
group: "sampling",
|
|
22793
|
+
options: ["none", "downsample_majority", "oversample_minority"],
|
|
22794
|
+
help: "Applied to the training split after extraction. Downsampling loses data but adds no duplicates; oversampling keeps all signal but repeats rows, which inflates confidence.",
|
|
22795
|
+
default: "downsample_majority"
|
|
22796
|
+
},
|
|
22797
|
+
{
|
|
22798
|
+
key: "min_golden_curators",
|
|
22799
|
+
camel: "minGoldenCurators",
|
|
22800
|
+
label: "Min curators for golden",
|
|
22801
|
+
kind: "number",
|
|
22802
|
+
group: "sampling",
|
|
22803
|
+
min: 1,
|
|
22804
|
+
integer: true,
|
|
22805
|
+
help: "Distinct human curators required on a workstream before its explicit labels are auto-promoted to golden.",
|
|
22806
|
+
default: 2
|
|
22807
|
+
},
|
|
22808
|
+
{
|
|
22809
|
+
key: "feedback_triage_max_contradictions",
|
|
22810
|
+
camel: "feedbackTriageMaxContradictions",
|
|
22811
|
+
label: "Feedback triage \u2014 max contradictions",
|
|
22812
|
+
kind: "number",
|
|
22813
|
+
group: "sampling",
|
|
22814
|
+
min: 1,
|
|
22815
|
+
integer: true,
|
|
22816
|
+
help: "A curator feedback event contradicted by more than this many other curators is held rather than turned into labels.",
|
|
22817
|
+
default: 1
|
|
22818
|
+
},
|
|
22819
|
+
{
|
|
22820
|
+
key: "feedback_triage_max_selection_size",
|
|
22821
|
+
camel: "feedbackTriageMaxSelectionSize",
|
|
22822
|
+
label: "Feedback triage \u2014 max selection",
|
|
22823
|
+
kind: "number",
|
|
22824
|
+
group: "sampling",
|
|
22825
|
+
min: 1,
|
|
22826
|
+
integer: true,
|
|
22827
|
+
help: "A feedback event selecting more activities than this is held (likely a bulk action, not a judgement).",
|
|
22828
|
+
default: 400
|
|
22829
|
+
},
|
|
22830
|
+
{
|
|
22831
|
+
key: "process_review_step_1",
|
|
22832
|
+
camel: "processReviewStep1",
|
|
22833
|
+
label: "Review at (step 1)",
|
|
22834
|
+
kind: "number",
|
|
22835
|
+
group: "review",
|
|
22836
|
+
min: 1,
|
|
22837
|
+
integer: true,
|
|
22838
|
+
help: "Members a process must reach before its first automated review (re-describe, rename, recategorize, drop unrelated members). Must be below step 2. Whether an org is reviewed at all is its mining_process_review feature flag.",
|
|
22839
|
+
default: 5
|
|
22840
|
+
},
|
|
22841
|
+
{
|
|
22842
|
+
key: "process_review_step_2",
|
|
22843
|
+
camel: "processReviewStep2",
|
|
22844
|
+
label: "Review again at (step 2)",
|
|
22845
|
+
kind: "number",
|
|
22846
|
+
group: "review",
|
|
22847
|
+
min: 2,
|
|
22848
|
+
integer: true,
|
|
22849
|
+
help: "Members at which the process is reviewed a second time, once more of it is known. Must be above step 1.",
|
|
22850
|
+
default: 10
|
|
22851
|
+
},
|
|
22852
|
+
{
|
|
22853
|
+
key: "notes",
|
|
22854
|
+
camel: "notes",
|
|
22855
|
+
label: "Notes",
|
|
22856
|
+
kind: "text",
|
|
22857
|
+
group: "meta",
|
|
22858
|
+
help: "Free-text admin note.",
|
|
22859
|
+
platformDefault: false
|
|
22860
|
+
}
|
|
22861
|
+
];
|
|
22862
|
+
MINING_PARAMETER_FIELDS = MINING_FIELDS.filter(
|
|
22863
|
+
(field) => field.platformDefault !== false
|
|
22864
|
+
);
|
|
22865
|
+
MINING_BUILTIN_DEFAULTS = Object.freeze(
|
|
22866
|
+
Object.fromEntries(
|
|
22867
|
+
MINING_FIELDS.filter((f) => f.default !== void 0).map((f) => [
|
|
22868
|
+
f.key,
|
|
22869
|
+
f.default
|
|
22870
|
+
])
|
|
22871
|
+
)
|
|
22872
|
+
);
|
|
22873
|
+
MINING_FIELDS_BY_KEY = new Map(
|
|
22874
|
+
MINING_FIELDS.map((f) => [f.key, f])
|
|
22875
|
+
);
|
|
22876
|
+
}
|
|
22877
|
+
});
|
|
22878
|
+
|
|
21835
22879
|
// ../../packages/@company/types/src/index.ts
|
|
21836
22880
|
var init_src5 = __esm({
|
|
21837
22881
|
"../../packages/@company/types/src/index.ts"() {
|
|
21838
22882
|
init_timeline();
|
|
22883
|
+
init_qna();
|
|
21839
22884
|
init_artifact();
|
|
21840
22885
|
init_taxonomy();
|
|
21841
22886
|
init_embedding();
|
|
21842
22887
|
init_repo_file_url();
|
|
21843
22888
|
init_query_dialect();
|
|
21844
22889
|
init_report_template();
|
|
22890
|
+
init_mining_config_fields();
|
|
21845
22891
|
}
|
|
21846
22892
|
});
|
|
21847
22893
|
|
|
@@ -21859,7 +22905,7 @@ var init_search_vector_write = __esm({
|
|
|
21859
22905
|
});
|
|
21860
22906
|
|
|
21861
22907
|
// ../../packages/@company/db/src/org-purge.ts
|
|
21862
|
-
var
|
|
22908
|
+
var observability5;
|
|
21863
22909
|
var init_org_purge = __esm({
|
|
21864
22910
|
"../../packages/@company/db/src/org-purge.ts"() {
|
|
21865
22911
|
"use strict";
|
|
@@ -21867,12 +22913,12 @@ var init_org_purge = __esm({
|
|
|
21867
22913
|
init_src2();
|
|
21868
22914
|
init_client();
|
|
21869
22915
|
init_org_context();
|
|
21870
|
-
|
|
22916
|
+
observability5 = createObservabilityService("org-purge");
|
|
21871
22917
|
}
|
|
21872
22918
|
});
|
|
21873
22919
|
|
|
21874
22920
|
// ../../packages/@company/db/src/org-orphan-scan.ts
|
|
21875
|
-
var
|
|
22921
|
+
var observability6;
|
|
21876
22922
|
var init_org_orphan_scan = __esm({
|
|
21877
22923
|
"../../packages/@company/db/src/org-orphan-scan.ts"() {
|
|
21878
22924
|
"use strict";
|
|
@@ -21880,7 +22926,7 @@ var init_org_orphan_scan = __esm({
|
|
|
21880
22926
|
init_src2();
|
|
21881
22927
|
init_org_context();
|
|
21882
22928
|
init_org_purge();
|
|
21883
|
-
|
|
22929
|
+
observability6 = createObservabilityService("org-orphan-scan");
|
|
21884
22930
|
}
|
|
21885
22931
|
});
|
|
21886
22932
|
|
|
@@ -21928,12 +22974,13 @@ var init_expert_areas = __esm({
|
|
|
21928
22974
|
});
|
|
21929
22975
|
|
|
21930
22976
|
// ../../packages/@company/db/src/exchange-context.ts
|
|
21931
|
-
var
|
|
22977
|
+
var observability7;
|
|
21932
22978
|
var init_exchange_context = __esm({
|
|
21933
22979
|
"../../packages/@company/db/src/exchange-context.ts"() {
|
|
21934
22980
|
"use strict";
|
|
21935
22981
|
init_src2();
|
|
21936
|
-
|
|
22982
|
+
init_org_context();
|
|
22983
|
+
observability7 = createObservabilityService("db-exchange-context");
|
|
21937
22984
|
}
|
|
21938
22985
|
});
|
|
21939
22986
|
|
|
@@ -21962,14 +23009,30 @@ var init_data_access = __esm({
|
|
|
21962
23009
|
}
|
|
21963
23010
|
});
|
|
21964
23011
|
|
|
23012
|
+
// ../../packages/@company/db/src/byod/host-guard.ts
|
|
23013
|
+
var init_host_guard = __esm({
|
|
23014
|
+
"../../packages/@company/db/src/byod/host-guard.ts"() {
|
|
23015
|
+
"use strict";
|
|
23016
|
+
}
|
|
23017
|
+
});
|
|
23018
|
+
|
|
23019
|
+
// ../../packages/@company/db/src/byod/admission-policy.ts
|
|
23020
|
+
var init_admission_policy = __esm({
|
|
23021
|
+
"../../packages/@company/db/src/byod/admission-policy.ts"() {
|
|
23022
|
+
"use strict";
|
|
23023
|
+
}
|
|
23024
|
+
});
|
|
23025
|
+
|
|
21965
23026
|
// ../../packages/@company/db/src/byod/pool-manager.ts
|
|
21966
|
-
var
|
|
23027
|
+
var observability8, IDLE_TIMEOUT_MS;
|
|
21967
23028
|
var init_pool_manager = __esm({
|
|
21968
23029
|
"../../packages/@company/db/src/byod/pool-manager.ts"() {
|
|
21969
23030
|
"use strict";
|
|
21970
23031
|
init_esm();
|
|
21971
23032
|
init_src2();
|
|
21972
|
-
|
|
23033
|
+
init_host_guard();
|
|
23034
|
+
init_admission_policy();
|
|
23035
|
+
observability8 = createObservabilityService("byod-pool-manager");
|
|
21973
23036
|
IDLE_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
21974
23037
|
}
|
|
21975
23038
|
});
|
|
@@ -21988,6 +23051,7 @@ var init_config_cache = __esm({
|
|
|
21988
23051
|
"use strict";
|
|
21989
23052
|
init_org_context();
|
|
21990
23053
|
init_degradation2();
|
|
23054
|
+
init_listener_connection();
|
|
21991
23055
|
}
|
|
21992
23056
|
});
|
|
21993
23057
|
|
|
@@ -22003,6 +23067,7 @@ var init_org_db_resolver = __esm({
|
|
|
22003
23067
|
"../../packages/@company/db/src/byod/org-db-resolver.ts"() {
|
|
22004
23068
|
"use strict";
|
|
22005
23069
|
init_pool_manager();
|
|
23070
|
+
init_admission_policy();
|
|
22006
23071
|
init_routed_pool();
|
|
22007
23072
|
}
|
|
22008
23073
|
});
|
|
@@ -22049,7 +23114,7 @@ function entry(database, dbName, table, orgScoping, opts = {}) {
|
|
|
22049
23114
|
identity: {
|
|
22050
23115
|
kind: "columns",
|
|
22051
23116
|
columns: opts.mergePolicy.identityKey,
|
|
22052
|
-
version: 1
|
|
23117
|
+
version: opts.identityVersion ?? 1
|
|
22053
23118
|
}
|
|
22054
23119
|
} : DEFAULT_RECONCILIATION)
|
|
22055
23120
|
};
|
|
@@ -22058,15 +23123,27 @@ function standardIntegrationTables(database, dbName) {
|
|
|
22058
23123
|
return [
|
|
22059
23124
|
entry(database, dbName, "source_events", "direct", {
|
|
22060
23125
|
scopingColumn: "organization_id",
|
|
23126
|
+
// v2: the identity gained source_account_id (A0).
|
|
23127
|
+
identityVersion: 2,
|
|
22061
23128
|
// PK `source_event_id` is a generated uuid; identity is the natural key.
|
|
22062
23129
|
// Two databases capturing the same event agree on the natural key and
|
|
22063
23130
|
// disagree on the uuid, so a PK arbiter never fires and the insert
|
|
22064
23131
|
// violates the natural key instead — the failure that made move-back
|
|
22065
|
-
// impossible.
|
|
22066
|
-
//
|
|
22067
|
-
//
|
|
23132
|
+
// impossible.
|
|
23133
|
+
//
|
|
23134
|
+
// The natural key includes the ACCOUNT (source-events-standard-tables/
|
|
23135
|
+
// 008): two accounts of one platform can produce the same
|
|
23136
|
+
// source_event_key and those are distinct events. While a destination
|
|
23137
|
+
// still has the old (org, platform, key) unique index, the copier's
|
|
23138
|
+
// preflight refuses to fold such rows together — see
|
|
23139
|
+
// `assertMergeKeysSafe` in migration-utils.ts.
|
|
22068
23140
|
mergePolicy: {
|
|
22069
|
-
identityKey: [
|
|
23141
|
+
identityKey: [
|
|
23142
|
+
"organization_id",
|
|
23143
|
+
"source_platform",
|
|
23144
|
+
"source_account_id",
|
|
23145
|
+
"source_event_key"
|
|
23146
|
+
],
|
|
22070
23147
|
// Keep the destination's uuid on conflict. NOT because it is the more
|
|
22071
23148
|
// referenced one — measured on dev, 6,124 of 7,717 referenced uuids
|
|
22072
23149
|
// (79%) existed only on the BYOD side — but because rewriting a primary
|
|
@@ -22132,6 +23209,14 @@ var init_table_registry = __esm({
|
|
|
22132
23209
|
entry("intelligence", INTELLIGENCE_DB, "qna_conversation_shares", "direct", {
|
|
22133
23210
|
scopingColumn: "organization_id"
|
|
22134
23211
|
}),
|
|
23212
|
+
// Charts saved with their answer (qna-charts/001); child of qna_messages.
|
|
23213
|
+
entry("intelligence", INTELLIGENCE_DB, "qna_charts", "direct", {
|
|
23214
|
+
scopingColumn: "organization_id"
|
|
23215
|
+
}),
|
|
23216
|
+
// Retry-safe Q&A writes + notification outbox (qna-charts/002).
|
|
23217
|
+
entry("intelligence", INTELLIGENCE_DB, "qna_write_operations", "direct", {
|
|
23218
|
+
scopingColumn: "organization_id"
|
|
23219
|
+
}),
|
|
22135
23220
|
entry("intelligence", INTELLIGENCE_DB, "incidents", "direct", {
|
|
22136
23221
|
scopingColumn: "organization_id",
|
|
22137
23222
|
hasVectorColumn: true
|
|
@@ -22214,6 +23299,14 @@ var init_table_registry = __esm({
|
|
|
22214
23299
|
entry("intelligence", INTELLIGENCE_DB, "expert_profile_facts", "direct", {
|
|
22215
23300
|
scopingColumn: "organization_id"
|
|
22216
23301
|
}),
|
|
23302
|
+
// Durable pending-decision queue for process membership (object-graph/113).
|
|
23303
|
+
entry("intelligence", INTELLIGENCE_DB, "mining_pending_decisions", "direct", {
|
|
23304
|
+
scopingColumn: "organization_id"
|
|
23305
|
+
}),
|
|
23306
|
+
// A member's "this wasn't me", awaiting the identities admin (object-graph/107).
|
|
23307
|
+
entry("intelligence", INTELLIGENCE_DB, "identity_disputes", "direct", {
|
|
23308
|
+
scopingColumn: "organization_id"
|
|
23309
|
+
}),
|
|
22217
23310
|
// Expert profile synthesis (object-graph/096).
|
|
22218
23311
|
entry("intelligence", INTELLIGENCE_DB, "expert_evidence_refs", "direct", {
|
|
22219
23312
|
scopingColumn: "organization_id"
|
|
@@ -22240,6 +23333,10 @@ var init_table_registry = __esm({
|
|
|
22240
23333
|
entry("intelligence", INTELLIGENCE_DB, "expert_area_merge_log", "direct", {
|
|
22241
23334
|
scopingColumn: "organization_id"
|
|
22242
23335
|
}),
|
|
23336
|
+
// Load-cycle gate for profile generation (object-graph/127).
|
|
23337
|
+
entry("intelligence", INTELLIGENCE_DB, "expert_load_cycle_state", "direct", {
|
|
23338
|
+
scopingColumn: "organization_id"
|
|
23339
|
+
}),
|
|
22243
23340
|
entry("intelligence", INTELLIGENCE_DB, "expert_profile_curation", "direct", {
|
|
22244
23341
|
scopingColumn: "organization_id"
|
|
22245
23342
|
}),
|
|
@@ -22266,12 +23363,53 @@ var init_table_registry = __esm({
|
|
|
22266
23363
|
entry("intelligence", INTELLIGENCE_DB, "digest_work_logs", "direct", {
|
|
22267
23364
|
scopingColumn: "organization_id"
|
|
22268
23365
|
}),
|
|
23366
|
+
// Onboarding guides (migrations/onboarding-guides/001): the guide lifecycle
|
|
23367
|
+
// row and its source refs. They reference report_onboarding rows in
|
|
23368
|
+
// knowledge_artifacts, so they ride on the same database as the artifacts.
|
|
23369
|
+
entry("intelligence", INTELLIGENCE_DB, "onboarding_guides", "direct", {
|
|
23370
|
+
scopingColumn: "organization_id"
|
|
23371
|
+
}),
|
|
23372
|
+
entry(
|
|
23373
|
+
"intelligence",
|
|
23374
|
+
INTELLIGENCE_DB,
|
|
23375
|
+
"onboarding_guide_source_refs",
|
|
23376
|
+
"direct",
|
|
23377
|
+
{ scopingColumn: "organization_id" }
|
|
23378
|
+
),
|
|
23379
|
+
// Memory → Skills (migrations/skills/001): lifecycle, revisions,
|
|
23380
|
+
// publications, dependencies and temporary Skillify output. skills and
|
|
23381
|
+
// skill_revisions reference `skill` rows in knowledge_artifacts, so they
|
|
23382
|
+
// ride on the same database as the artifacts.
|
|
23383
|
+
entry("intelligence", INTELLIGENCE_DB, "skills", "direct", {
|
|
23384
|
+
scopingColumn: "organization_id"
|
|
23385
|
+
}),
|
|
23386
|
+
entry("intelligence", INTELLIGENCE_DB, "skill_revisions", "direct", {
|
|
23387
|
+
scopingColumn: "organization_id"
|
|
23388
|
+
}),
|
|
23389
|
+
entry("intelligence", INTELLIGENCE_DB, "skill_publications", "direct", {
|
|
23390
|
+
scopingColumn: "organization_id"
|
|
23391
|
+
}),
|
|
23392
|
+
entry("intelligence", INTELLIGENCE_DB, "skill_sources", "direct", {
|
|
23393
|
+
scopingColumn: "organization_id"
|
|
23394
|
+
}),
|
|
23395
|
+
entry("intelligence", INTELLIGENCE_DB, "skill_generation_outputs", "direct", {
|
|
23396
|
+
scopingColumn: "organization_id"
|
|
23397
|
+
}),
|
|
22269
23398
|
entry("intelligence", INTELLIGENCE_DB, "activity_graph_edges", "direct", {
|
|
22270
23399
|
scopingColumn: "organization_id"
|
|
22271
23400
|
}),
|
|
22272
23401
|
entry("intelligence", INTELLIGENCE_DB, "process_registry", "direct", {
|
|
22273
23402
|
scopingColumn: "organization_id"
|
|
22274
23403
|
}),
|
|
23404
|
+
// Append-only history of a process's scored state (object-graph/114). After
|
|
23405
|
+
// process_registry: composite FK to it.
|
|
23406
|
+
entry("intelligence", INTELLIGENCE_DB, "process_state_history", "direct", {
|
|
23407
|
+
scopingColumn: "organization_id"
|
|
23408
|
+
}),
|
|
23409
|
+
// Late live events awaiting a windowed replay (object-graph/115).
|
|
23410
|
+
entry("intelligence", INTELLIGENCE_DB, "mining_awaiting_replay", "direct", {
|
|
23411
|
+
scopingColumn: "organization_id"
|
|
23412
|
+
}),
|
|
22275
23413
|
// Incident overlay + evidence signals + audit — the incident-specific
|
|
22276
23414
|
// projection keyed by (organization_id, process_id) on top of
|
|
22277
23415
|
// process_registry (category='incident_response'). Rides to BYOD with the
|
|
@@ -22385,19 +23523,12 @@ var init_table_registry = __esm({
|
|
|
22385
23523
|
entry("intelligence", INTELLIGENCE_DB, "artifact_cluster_members", "direct", {
|
|
22386
23524
|
scopingColumn: "organization_id"
|
|
22387
23525
|
}),
|
|
22388
|
-
// Graph-enrichment watermark + deadletter ride to BYOD with the object graph
|
|
22389
|
-
// they walk. audit round 4 (#3).
|
|
22390
|
-
entry("intelligence", INTELLIGENCE_DB, "graph_enrichment_state", "direct", {
|
|
22391
|
-
scopingColumn: "organization_id"
|
|
22392
|
-
}),
|
|
22393
23526
|
entry(
|
|
22394
23527
|
"intelligence",
|
|
22395
23528
|
INTELLIGENCE_DB,
|
|
22396
|
-
"
|
|
23529
|
+
"artifact_cluster_workstreams",
|
|
22397
23530
|
"direct",
|
|
22398
|
-
{
|
|
22399
|
-
scopingColumn: "organization_id"
|
|
22400
|
-
}
|
|
23531
|
+
{ scopingColumn: "organization_id" }
|
|
22401
23532
|
)
|
|
22402
23533
|
];
|
|
22403
23534
|
INTEGRATIONS_DB = "haansi_integrations_prod";
|
|
@@ -22424,6 +23555,7 @@ var init_schema_provisioner = __esm({
|
|
|
22424
23555
|
path = __toESM(require("path"));
|
|
22425
23556
|
init_src2();
|
|
22426
23557
|
init_pool_manager();
|
|
23558
|
+
init_host_guard();
|
|
22427
23559
|
init_table_registry();
|
|
22428
23560
|
SCHEMAS_DIR = path.join(__dirname, "schemas");
|
|
22429
23561
|
logger2 = createLogger("db-byod-schema-provisioner");
|
|
@@ -22431,7 +23563,7 @@ var init_schema_provisioner = __esm({
|
|
|
22431
23563
|
});
|
|
22432
23564
|
|
|
22433
23565
|
// ../../packages/@company/db/src/byod/host-resolver.ts
|
|
22434
|
-
var
|
|
23566
|
+
var observability9;
|
|
22435
23567
|
var init_host_resolver = __esm({
|
|
22436
23568
|
"../../packages/@company/db/src/byod/host-resolver.ts"() {
|
|
22437
23569
|
"use strict";
|
|
@@ -22439,7 +23571,9 @@ var init_host_resolver = __esm({
|
|
|
22439
23571
|
init_src2();
|
|
22440
23572
|
init_config_cache();
|
|
22441
23573
|
init_pool_manager();
|
|
22442
|
-
|
|
23574
|
+
init_host_guard();
|
|
23575
|
+
init_admission_policy();
|
|
23576
|
+
observability9 = createObservabilityService("byod-host-resolver");
|
|
22443
23577
|
}
|
|
22444
23578
|
});
|
|
22445
23579
|
|
|
@@ -23367,6 +24501,7 @@ var init_migration_service = __esm({
|
|
|
23367
24501
|
"use strict";
|
|
23368
24502
|
init_esm();
|
|
23369
24503
|
init_pool_manager();
|
|
24504
|
+
init_host_guard();
|
|
23370
24505
|
init_org_context();
|
|
23371
24506
|
init_client();
|
|
23372
24507
|
init_src2();
|
|
@@ -23401,6 +24536,8 @@ var init_byod = __esm({
|
|
|
23401
24536
|
"../../packages/@company/db/src/byod/index.ts"() {
|
|
23402
24537
|
"use strict";
|
|
23403
24538
|
init_pool_manager();
|
|
24539
|
+
init_host_guard();
|
|
24540
|
+
init_admission_policy();
|
|
23404
24541
|
init_config_cache();
|
|
23405
24542
|
init_control_plane_residency();
|
|
23406
24543
|
init_integration_storage();
|
|
@@ -23433,7 +24570,9 @@ var init_report_generation_jobs = __esm({
|
|
|
23433
24570
|
var init_src6 = __esm({
|
|
23434
24571
|
"../../packages/@company/db/src/index.ts"() {
|
|
23435
24572
|
init_client();
|
|
24573
|
+
init_listener_connection();
|
|
23436
24574
|
init_org_context();
|
|
24575
|
+
init_admin_pools();
|
|
23437
24576
|
init_search_vector_write();
|
|
23438
24577
|
init_org_purge();
|
|
23439
24578
|
init_org_orphan_scan();
|
|
@@ -80020,10 +81159,10 @@ __export(setup_mcp_exports, {
|
|
|
80020
81159
|
});
|
|
80021
81160
|
function parseTarget(arg) {
|
|
80022
81161
|
if (!arg || arg === "all") return "all";
|
|
80023
|
-
if (arg === "solutions" || arg === "exchange" || arg === "digests")
|
|
81162
|
+
if (arg === "solutions" || arg === "exchange" || arg === "digests" || arg === "onboarding" || arg === "skills")
|
|
80024
81163
|
return arg;
|
|
80025
81164
|
throw new Error(
|
|
80026
|
-
`Unknown target: ${arg}. Use one of: solutions, exchange, digests, all (default).`
|
|
81165
|
+
`Unknown target: ${arg}. Use one of: solutions, exchange, digests, onboarding, skills, all (default).`
|
|
80027
81166
|
);
|
|
80028
81167
|
}
|
|
80029
81168
|
function httpServerUrl(path2) {
|
|
@@ -80156,6 +81295,20 @@ var init_setup_mcp = __esm({
|
|
|
80156
81295
|
target: "digests",
|
|
80157
81296
|
name: "haansi-digests",
|
|
80158
81297
|
path: "/api/v1/memory/digests/mcp"
|
|
81298
|
+
},
|
|
81299
|
+
// Published onboarding guides, so an agent can pick up a workstream from
|
|
81300
|
+
// its handoff doc (docs/product/plans/2026-09-24-onboarding-guides.md §8.3).
|
|
81301
|
+
{
|
|
81302
|
+
target: "onboarding",
|
|
81303
|
+
name: "haansi-onboarding",
|
|
81304
|
+
path: "/api/v1/memory/onboarding/mcp"
|
|
81305
|
+
},
|
|
81306
|
+
// Published team skills, loaded progressively by coding agents
|
|
81307
|
+
// (docs/product/plans/2026-10-10-memory-skills.md §7).
|
|
81308
|
+
{
|
|
81309
|
+
target: "skills",
|
|
81310
|
+
name: "haansi-skills",
|
|
81311
|
+
path: "/api/v1/memory/skills/mcp"
|
|
80159
81312
|
}
|
|
80160
81313
|
];
|
|
80161
81314
|
WRITERS = {
|