haansi 0.1.45 → 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 +1152 -35
- 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
|
|
|
@@ -21545,12 +21730,23 @@ var init_listener_connection = __esm({
|
|
|
21545
21730
|
}
|
|
21546
21731
|
});
|
|
21547
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
|
+
|
|
21548
21743
|
// ../../packages/@company/db/src/byod/routed-pool.ts
|
|
21549
21744
|
var logger, ROUTED_TENANT_CONTEXT, ROUTED_TENANT_RAW_POOL, ADMITTED_TENANT_CONTEXT;
|
|
21550
21745
|
var init_routed_pool = __esm({
|
|
21551
21746
|
"../../packages/@company/db/src/byod/routed-pool.ts"() {
|
|
21552
21747
|
"use strict";
|
|
21553
21748
|
init_src2();
|
|
21749
|
+
init_release_after_callback();
|
|
21554
21750
|
logger = createLogger("db-byod-routed-pool");
|
|
21555
21751
|
ROUTED_TENANT_CONTEXT = Symbol.for("haansi.db.routedTenantContext");
|
|
21556
21752
|
ROUTED_TENANT_RAW_POOL = Symbol.for("haansi.db.routedTenantRawPool");
|
|
@@ -21559,18 +21755,28 @@ var init_routed_pool = __esm({
|
|
|
21559
21755
|
});
|
|
21560
21756
|
|
|
21561
21757
|
// ../../packages/@company/db/src/org-context.ts
|
|
21562
|
-
var
|
|
21758
|
+
var observability4, DECRYPTING_CLIENT;
|
|
21563
21759
|
var init_org_context = __esm({
|
|
21564
21760
|
"../../packages/@company/db/src/org-context.ts"() {
|
|
21565
21761
|
"use strict";
|
|
21566
21762
|
init_src4();
|
|
21567
21763
|
init_src2();
|
|
21568
21764
|
init_routed_pool();
|
|
21569
|
-
|
|
21765
|
+
init_release_after_callback();
|
|
21766
|
+
observability4 = createObservabilityService("db-org-context");
|
|
21570
21767
|
DECRYPTING_CLIENT = Symbol.for("haansi.db.decryptingClient");
|
|
21571
21768
|
}
|
|
21572
21769
|
});
|
|
21573
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
|
+
|
|
21574
21780
|
// ../../packages/@company/types/src/timeline.ts
|
|
21575
21781
|
var init_timeline = __esm({
|
|
21576
21782
|
"../../packages/@company/types/src/timeline.ts"() {
|
|
@@ -21578,6 +21784,13 @@ var init_timeline = __esm({
|
|
|
21578
21784
|
}
|
|
21579
21785
|
});
|
|
21580
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
|
+
|
|
21581
21794
|
// ../../packages/@company/types/src/artifact.ts
|
|
21582
21795
|
var init_artifact = __esm({
|
|
21583
21796
|
"../../packages/@company/types/src/artifact.ts"() {
|
|
@@ -21706,10 +21919,10 @@ var init_taxonomy = __esm({
|
|
|
21706
21919
|
category: "report",
|
|
21707
21920
|
label: "Onboarding Guide",
|
|
21708
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.",
|
|
21709
|
-
icon: "
|
|
21922
|
+
icon: "Sprout",
|
|
21710
21923
|
aliases: ["onboarding_packet", "onboarding-packet"],
|
|
21711
21924
|
autoApproved: false,
|
|
21712
|
-
producedBy: ["POST /api/v1/memory/
|
|
21925
|
+
producedBy: ["POST /api/v1/memory/onboarding/guides/:id/generate"],
|
|
21713
21926
|
// docs/product/plans/2026-09-24-onboarding-guides.md D11: no generic
|
|
21714
21927
|
// reader or writer may touch a guide.
|
|
21715
21928
|
reserved: true
|
|
@@ -21721,7 +21934,9 @@ var init_taxonomy = __esm({
|
|
|
21721
21934
|
icon: "GitPullRequest",
|
|
21722
21935
|
aliases: ["pr_context", "pr-context"],
|
|
21723
21936
|
autoApproved: true,
|
|
21724
|
-
|
|
21937
|
+
// PR generation is parked until workstream-backed context retrieval exists.
|
|
21938
|
+
// producedBy: ["POST /api/v1/memory/reports/pr"],
|
|
21939
|
+
producedBy: []
|
|
21725
21940
|
},
|
|
21726
21941
|
expert: {
|
|
21727
21942
|
category: "expert",
|
|
@@ -21752,6 +21967,18 @@ var init_taxonomy = __esm({
|
|
|
21752
21967
|
autoApproved: true,
|
|
21753
21968
|
producedBy: ["POST /api/v1/memory/recall/messages/:id/feedback"]
|
|
21754
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
|
+
},
|
|
21755
21982
|
digest_entry: {
|
|
21756
21983
|
category: "digest",
|
|
21757
21984
|
label: "Digest Entry",
|
|
@@ -21842,16 +22069,825 @@ var init_report_template = __esm({
|
|
|
21842
22069
|
}
|
|
21843
22070
|
});
|
|
21844
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
|
+
|
|
21845
22879
|
// ../../packages/@company/types/src/index.ts
|
|
21846
22880
|
var init_src5 = __esm({
|
|
21847
22881
|
"../../packages/@company/types/src/index.ts"() {
|
|
21848
22882
|
init_timeline();
|
|
22883
|
+
init_qna();
|
|
21849
22884
|
init_artifact();
|
|
21850
22885
|
init_taxonomy();
|
|
21851
22886
|
init_embedding();
|
|
21852
22887
|
init_repo_file_url();
|
|
21853
22888
|
init_query_dialect();
|
|
21854
22889
|
init_report_template();
|
|
22890
|
+
init_mining_config_fields();
|
|
21855
22891
|
}
|
|
21856
22892
|
});
|
|
21857
22893
|
|
|
@@ -21869,7 +22905,7 @@ var init_search_vector_write = __esm({
|
|
|
21869
22905
|
});
|
|
21870
22906
|
|
|
21871
22907
|
// ../../packages/@company/db/src/org-purge.ts
|
|
21872
|
-
var
|
|
22908
|
+
var observability5;
|
|
21873
22909
|
var init_org_purge = __esm({
|
|
21874
22910
|
"../../packages/@company/db/src/org-purge.ts"() {
|
|
21875
22911
|
"use strict";
|
|
@@ -21877,12 +22913,12 @@ var init_org_purge = __esm({
|
|
|
21877
22913
|
init_src2();
|
|
21878
22914
|
init_client();
|
|
21879
22915
|
init_org_context();
|
|
21880
|
-
|
|
22916
|
+
observability5 = createObservabilityService("org-purge");
|
|
21881
22917
|
}
|
|
21882
22918
|
});
|
|
21883
22919
|
|
|
21884
22920
|
// ../../packages/@company/db/src/org-orphan-scan.ts
|
|
21885
|
-
var
|
|
22921
|
+
var observability6;
|
|
21886
22922
|
var init_org_orphan_scan = __esm({
|
|
21887
22923
|
"../../packages/@company/db/src/org-orphan-scan.ts"() {
|
|
21888
22924
|
"use strict";
|
|
@@ -21890,7 +22926,7 @@ var init_org_orphan_scan = __esm({
|
|
|
21890
22926
|
init_src2();
|
|
21891
22927
|
init_org_context();
|
|
21892
22928
|
init_org_purge();
|
|
21893
|
-
|
|
22929
|
+
observability6 = createObservabilityService("org-orphan-scan");
|
|
21894
22930
|
}
|
|
21895
22931
|
});
|
|
21896
22932
|
|
|
@@ -21938,12 +22974,13 @@ var init_expert_areas = __esm({
|
|
|
21938
22974
|
});
|
|
21939
22975
|
|
|
21940
22976
|
// ../../packages/@company/db/src/exchange-context.ts
|
|
21941
|
-
var
|
|
22977
|
+
var observability7;
|
|
21942
22978
|
var init_exchange_context = __esm({
|
|
21943
22979
|
"../../packages/@company/db/src/exchange-context.ts"() {
|
|
21944
22980
|
"use strict";
|
|
21945
22981
|
init_src2();
|
|
21946
|
-
|
|
22982
|
+
init_org_context();
|
|
22983
|
+
observability7 = createObservabilityService("db-exchange-context");
|
|
21947
22984
|
}
|
|
21948
22985
|
});
|
|
21949
22986
|
|
|
@@ -21972,14 +23009,30 @@ var init_data_access = __esm({
|
|
|
21972
23009
|
}
|
|
21973
23010
|
});
|
|
21974
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
|
+
|
|
21975
23026
|
// ../../packages/@company/db/src/byod/pool-manager.ts
|
|
21976
|
-
var
|
|
23027
|
+
var observability8, IDLE_TIMEOUT_MS;
|
|
21977
23028
|
var init_pool_manager = __esm({
|
|
21978
23029
|
"../../packages/@company/db/src/byod/pool-manager.ts"() {
|
|
21979
23030
|
"use strict";
|
|
21980
23031
|
init_esm();
|
|
21981
23032
|
init_src2();
|
|
21982
|
-
|
|
23033
|
+
init_host_guard();
|
|
23034
|
+
init_admission_policy();
|
|
23035
|
+
observability8 = createObservabilityService("byod-pool-manager");
|
|
21983
23036
|
IDLE_TIMEOUT_MS = 5 * 60 * 1e3;
|
|
21984
23037
|
}
|
|
21985
23038
|
});
|
|
@@ -22014,6 +23067,7 @@ var init_org_db_resolver = __esm({
|
|
|
22014
23067
|
"../../packages/@company/db/src/byod/org-db-resolver.ts"() {
|
|
22015
23068
|
"use strict";
|
|
22016
23069
|
init_pool_manager();
|
|
23070
|
+
init_admission_policy();
|
|
22017
23071
|
init_routed_pool();
|
|
22018
23072
|
}
|
|
22019
23073
|
});
|
|
@@ -22060,7 +23114,7 @@ function entry(database, dbName, table, orgScoping, opts = {}) {
|
|
|
22060
23114
|
identity: {
|
|
22061
23115
|
kind: "columns",
|
|
22062
23116
|
columns: opts.mergePolicy.identityKey,
|
|
22063
|
-
version: 1
|
|
23117
|
+
version: opts.identityVersion ?? 1
|
|
22064
23118
|
}
|
|
22065
23119
|
} : DEFAULT_RECONCILIATION)
|
|
22066
23120
|
};
|
|
@@ -22069,15 +23123,27 @@ function standardIntegrationTables(database, dbName) {
|
|
|
22069
23123
|
return [
|
|
22070
23124
|
entry(database, dbName, "source_events", "direct", {
|
|
22071
23125
|
scopingColumn: "organization_id",
|
|
23126
|
+
// v2: the identity gained source_account_id (A0).
|
|
23127
|
+
identityVersion: 2,
|
|
22072
23128
|
// PK `source_event_id` is a generated uuid; identity is the natural key.
|
|
22073
23129
|
// Two databases capturing the same event agree on the natural key and
|
|
22074
23130
|
// disagree on the uuid, so a PK arbiter never fires and the insert
|
|
22075
23131
|
// violates the natural key instead — the failure that made move-back
|
|
22076
|
-
// impossible.
|
|
22077
|
-
//
|
|
22078
|
-
//
|
|
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.
|
|
22079
23140
|
mergePolicy: {
|
|
22080
|
-
identityKey: [
|
|
23141
|
+
identityKey: [
|
|
23142
|
+
"organization_id",
|
|
23143
|
+
"source_platform",
|
|
23144
|
+
"source_account_id",
|
|
23145
|
+
"source_event_key"
|
|
23146
|
+
],
|
|
22081
23147
|
// Keep the destination's uuid on conflict. NOT because it is the more
|
|
22082
23148
|
// referenced one — measured on dev, 6,124 of 7,717 referenced uuids
|
|
22083
23149
|
// (79%) existed only on the BYOD side — but because rewriting a primary
|
|
@@ -22143,6 +23209,14 @@ var init_table_registry = __esm({
|
|
|
22143
23209
|
entry("intelligence", INTELLIGENCE_DB, "qna_conversation_shares", "direct", {
|
|
22144
23210
|
scopingColumn: "organization_id"
|
|
22145
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
|
+
}),
|
|
22146
23220
|
entry("intelligence", INTELLIGENCE_DB, "incidents", "direct", {
|
|
22147
23221
|
scopingColumn: "organization_id",
|
|
22148
23222
|
hasVectorColumn: true
|
|
@@ -22225,6 +23299,10 @@ var init_table_registry = __esm({
|
|
|
22225
23299
|
entry("intelligence", INTELLIGENCE_DB, "expert_profile_facts", "direct", {
|
|
22226
23300
|
scopingColumn: "organization_id"
|
|
22227
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
|
+
}),
|
|
22228
23306
|
// A member's "this wasn't me", awaiting the identities admin (object-graph/107).
|
|
22229
23307
|
entry("intelligence", INTELLIGENCE_DB, "identity_disputes", "direct", {
|
|
22230
23308
|
scopingColumn: "organization_id"
|
|
@@ -22255,6 +23333,10 @@ var init_table_registry = __esm({
|
|
|
22255
23333
|
entry("intelligence", INTELLIGENCE_DB, "expert_area_merge_log", "direct", {
|
|
22256
23334
|
scopingColumn: "organization_id"
|
|
22257
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
|
+
}),
|
|
22258
23340
|
entry("intelligence", INTELLIGENCE_DB, "expert_profile_curation", "direct", {
|
|
22259
23341
|
scopingColumn: "organization_id"
|
|
22260
23342
|
}),
|
|
@@ -22294,12 +23376,40 @@ var init_table_registry = __esm({
|
|
|
22294
23376
|
"direct",
|
|
22295
23377
|
{ scopingColumn: "organization_id" }
|
|
22296
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
|
+
}),
|
|
22297
23398
|
entry("intelligence", INTELLIGENCE_DB, "activity_graph_edges", "direct", {
|
|
22298
23399
|
scopingColumn: "organization_id"
|
|
22299
23400
|
}),
|
|
22300
23401
|
entry("intelligence", INTELLIGENCE_DB, "process_registry", "direct", {
|
|
22301
23402
|
scopingColumn: "organization_id"
|
|
22302
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
|
+
}),
|
|
22303
23413
|
// Incident overlay + evidence signals + audit — the incident-specific
|
|
22304
23414
|
// projection keyed by (organization_id, process_id) on top of
|
|
22305
23415
|
// process_registry (category='incident_response'). Rides to BYOD with the
|
|
@@ -22413,19 +23523,12 @@ var init_table_registry = __esm({
|
|
|
22413
23523
|
entry("intelligence", INTELLIGENCE_DB, "artifact_cluster_members", "direct", {
|
|
22414
23524
|
scopingColumn: "organization_id"
|
|
22415
23525
|
}),
|
|
22416
|
-
// Graph-enrichment watermark + deadletter ride to BYOD with the object graph
|
|
22417
|
-
// they walk. audit round 4 (#3).
|
|
22418
|
-
entry("intelligence", INTELLIGENCE_DB, "graph_enrichment_state", "direct", {
|
|
22419
|
-
scopingColumn: "organization_id"
|
|
22420
|
-
}),
|
|
22421
23526
|
entry(
|
|
22422
23527
|
"intelligence",
|
|
22423
23528
|
INTELLIGENCE_DB,
|
|
22424
|
-
"
|
|
23529
|
+
"artifact_cluster_workstreams",
|
|
22425
23530
|
"direct",
|
|
22426
|
-
{
|
|
22427
|
-
scopingColumn: "organization_id"
|
|
22428
|
-
}
|
|
23531
|
+
{ scopingColumn: "organization_id" }
|
|
22429
23532
|
)
|
|
22430
23533
|
];
|
|
22431
23534
|
INTEGRATIONS_DB = "haansi_integrations_prod";
|
|
@@ -22452,6 +23555,7 @@ var init_schema_provisioner = __esm({
|
|
|
22452
23555
|
path = __toESM(require("path"));
|
|
22453
23556
|
init_src2();
|
|
22454
23557
|
init_pool_manager();
|
|
23558
|
+
init_host_guard();
|
|
22455
23559
|
init_table_registry();
|
|
22456
23560
|
SCHEMAS_DIR = path.join(__dirname, "schemas");
|
|
22457
23561
|
logger2 = createLogger("db-byod-schema-provisioner");
|
|
@@ -22459,7 +23563,7 @@ var init_schema_provisioner = __esm({
|
|
|
22459
23563
|
});
|
|
22460
23564
|
|
|
22461
23565
|
// ../../packages/@company/db/src/byod/host-resolver.ts
|
|
22462
|
-
var
|
|
23566
|
+
var observability9;
|
|
22463
23567
|
var init_host_resolver = __esm({
|
|
22464
23568
|
"../../packages/@company/db/src/byod/host-resolver.ts"() {
|
|
22465
23569
|
"use strict";
|
|
@@ -22467,7 +23571,9 @@ var init_host_resolver = __esm({
|
|
|
22467
23571
|
init_src2();
|
|
22468
23572
|
init_config_cache();
|
|
22469
23573
|
init_pool_manager();
|
|
22470
|
-
|
|
23574
|
+
init_host_guard();
|
|
23575
|
+
init_admission_policy();
|
|
23576
|
+
observability9 = createObservabilityService("byod-host-resolver");
|
|
22471
23577
|
}
|
|
22472
23578
|
});
|
|
22473
23579
|
|
|
@@ -23395,6 +24501,7 @@ var init_migration_service = __esm({
|
|
|
23395
24501
|
"use strict";
|
|
23396
24502
|
init_esm();
|
|
23397
24503
|
init_pool_manager();
|
|
24504
|
+
init_host_guard();
|
|
23398
24505
|
init_org_context();
|
|
23399
24506
|
init_client();
|
|
23400
24507
|
init_src2();
|
|
@@ -23429,6 +24536,8 @@ var init_byod = __esm({
|
|
|
23429
24536
|
"../../packages/@company/db/src/byod/index.ts"() {
|
|
23430
24537
|
"use strict";
|
|
23431
24538
|
init_pool_manager();
|
|
24539
|
+
init_host_guard();
|
|
24540
|
+
init_admission_policy();
|
|
23432
24541
|
init_config_cache();
|
|
23433
24542
|
init_control_plane_residency();
|
|
23434
24543
|
init_integration_storage();
|
|
@@ -23463,6 +24572,7 @@ var init_src6 = __esm({
|
|
|
23463
24572
|
init_client();
|
|
23464
24573
|
init_listener_connection();
|
|
23465
24574
|
init_org_context();
|
|
24575
|
+
init_admin_pools();
|
|
23466
24576
|
init_search_vector_write();
|
|
23467
24577
|
init_org_purge();
|
|
23468
24578
|
init_org_orphan_scan();
|
|
@@ -80049,10 +81159,10 @@ __export(setup_mcp_exports, {
|
|
|
80049
81159
|
});
|
|
80050
81160
|
function parseTarget(arg) {
|
|
80051
81161
|
if (!arg || arg === "all") return "all";
|
|
80052
|
-
if (arg === "solutions" || arg === "exchange" || arg === "digests" || arg === "onboarding")
|
|
81162
|
+
if (arg === "solutions" || arg === "exchange" || arg === "digests" || arg === "onboarding" || arg === "skills")
|
|
80053
81163
|
return arg;
|
|
80054
81164
|
throw new Error(
|
|
80055
|
-
`Unknown target: ${arg}. Use one of: solutions, exchange, digests, onboarding, all (default).`
|
|
81165
|
+
`Unknown target: ${arg}. Use one of: solutions, exchange, digests, onboarding, skills, all (default).`
|
|
80056
81166
|
);
|
|
80057
81167
|
}
|
|
80058
81168
|
function httpServerUrl(path2) {
|
|
@@ -80192,6 +81302,13 @@ var init_setup_mcp = __esm({
|
|
|
80192
81302
|
target: "onboarding",
|
|
80193
81303
|
name: "haansi-onboarding",
|
|
80194
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"
|
|
80195
81312
|
}
|
|
80196
81313
|
];
|
|
80197
81314
|
WRITERS = {
|